1 /* Next Runtime (ABI-0/1) private.
2    Copyright (C) 2011-2022 Free Software Foundation, Inc.
3    Contributed by Iain Sandoe (split from objc-act.cc)
4 
5 This file is part of GCC.
6 
7 GCC is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3, or (at your option)
10 any later version.
11 
12 GCC is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 GNU General Public License for more details.
16 
17 You should have received a copy of the GNU General Public License
18 along with GCC; see the file COPYING3.  If not see
19 <http://www.gnu.org/licenses/>.  */
20 
21 /* This implements the original NeXT ABI (0) used for m32 code and
22    indicated by module version 6.  It also implements the small number
23    of additions made for properties and optional protocol methods as
24    ABI=1 (module version 7).  */
25 
26 #include "config.h"
27 #include "system.h"
28 #include "coretypes.h"
29 #include "tree.h"
30 #include "stringpool.h"
31 #include "attribs.h"
32 
33 #ifdef OBJCPLUS
34 #include "cp/cp-tree.h"
35 #else
36 #include "c/c-tree.h"
37 #include "c/c-lang.h"
38 #endif
39 #include "langhooks.h"
40 #include "c-family/c-objc.h"
41 #include "objc-act.h"
42 #include "opts.h"
43 
44 /* When building Objective-C++, we are not linking against the C
45    front-end and so need to replicate the C tree-construction
46    functions in some way.  */
47 #ifdef OBJCPLUS
48 #define OBJCP_REMAP_FUNCTIONS
49 #include "objcp-decl.h"
50 #endif  /* OBJCPLUS */
51 
52 #include "target.h"
53 #include "c-family/c-target.h"
54 #include "tree-iterator.h"
55 
56 #include "objc-runtime-hooks.h"
57 #include "objc-runtime-shared-support.h"
58 #include "objc-next-metadata-tags.h"
59 #include "objc-encoding.h"
60 
61 /* NeXT ABI 0 and 1 private definitions.  */
62 #define DEF_CONSTANT_STRING_CLASS_NAME "NSConstantString"
63 
64 #define TAG_GETCLASS			"objc_getClass"
65 #define TAG_GETMETACLASS		"objc_getMetaClass"
66 
67 #define TAG_MSGSEND			"objc_msgSend"
68 #define TAG_MSGSENDSUPER		"objc_msgSendSuper"
69 #define TAG_MSGSEND_STRET		"objc_msgSend_stret"
70 #define TAG_MSGSENDSUPER_STRET		"objc_msgSendSuper_stret"
71 
72 /* NeXT-specific tags.  */
73 
74 #define TAG_MSGSEND_NONNIL		"objc_msgSendNonNil"
75 #define TAG_MSGSEND_NONNIL_STRET	"objc_msgSendNonNil_stret"
76 #define TAG_EXCEPTIONEXTRACT		"objc_exception_extract"
77 #define TAG_EXCEPTIONTRYENTER		"objc_exception_try_enter"
78 #define TAG_EXCEPTIONTRYEXIT		"objc_exception_try_exit"
79 #define TAG_EXCEPTIONMATCH		"objc_exception_match"
80 #define TAG_SETJMP			"_setjmp"
81 
82 #define TAG_ASSIGNIVAR			"objc_assign_ivar"
83 #define TAG_ASSIGNGLOBAL		"objc_assign_global"
84 #define TAG_ASSIGNSTRONGCAST		"objc_assign_strongCast"
85 
86 /* Branch entry points.  All that matters here are the addresses;
87    functions with these names do not really exist in libobjc.  */
88 
89 #define TAG_MSGSEND_FAST		"objc_msgSend_Fast"
90 #define TAG_ASSIGNIVAR_FAST		"objc_assign_ivar_Fast"
91 
92 /* The version identifies which language generation and runtime the
93    module (file) was compiled for, and is recorded in the module
94    descriptor.  */
95 #define OBJC_VERSION			(flag_objc_abi >= 1 ? 7 : 6)
96 
97 #define UTAG_CLASS_EXT			"_objc_class_ext"
98 #define UTAG_PROPERTY_LIST		"_prop_list_t"
99 #define UTAG_PROTOCOL_EXT		"_objc_protocol_extension"
100 
101 #define CLS_HAS_CXX_STRUCTORS		0x2000L
102 
103 static void next_runtime_01_initialize (void);
104 
105 static tree next_runtime_abi_01_super_superclassfield_id (void);
106 
107 static tree next_runtime_abi_01_class_decl (tree);
108 static tree next_runtime_abi_01_metaclass_decl (tree);
109 static tree next_runtime_abi_01_category_decl (tree);
110 static tree next_runtime_abi_01_protocol_decl (tree);
111 static tree next_runtime_abi_01_string_decl (tree, const char *, string_section);
112 
113 static tree next_runtime_abi_01_get_class_reference (tree);
114 static tree next_runtime_abi_01_build_selector_reference (location_t, tree, tree);
115 static tree next_runtime_abi_01_get_protocol_reference (location_t, tree);
116 static tree next_runtime_abi_01_build_ivar_ref (location_t, tree, tree);
117 static tree next_runtime_abi_01_get_class_super_ref (location_t, struct imp_entry *, bool);
118 static tree next_runtime_abi_01_get_category_super_ref (location_t, struct imp_entry *, bool);
119 
120 static tree next_runtime_abi_01_receiver_is_class_object (tree);
121 static void next_runtime_abi_01_get_arg_type_list_base (vec<tree, va_gc> **,
122 							tree, int, int);
123 static tree next_runtime_abi_01_build_objc_method_call (location_t, tree, tree,
124 							tree, tree, tree, int);
125 static bool next_runtime_abi_01_setup_const_string_class_decl (void);
126 static tree next_runtime_abi_01_build_const_string_constructor (location_t, tree, int);
127 
128 static void objc_generate_v1_next_metadata (void);
129 
130 static void build_next_objc_exception_stuff (void);
131 static tree objc_eh_runtime_type (tree type);
132 static tree objc_eh_personality (void);
133 static tree build_throw_stmt (location_t, tree, bool);
134 static tree objc_build_exc_ptr (struct objc_try_context **);
135 static tree begin_catch (struct objc_try_context **, tree, tree, tree, bool);
136 static void finish_catch (struct objc_try_context **, tree);
137 static tree finish_try_stmt (struct objc_try_context **);
138 
139 bool
objc_next_runtime_abi_01_init(objc_runtime_hooks * rthooks)140 objc_next_runtime_abi_01_init (objc_runtime_hooks *rthooks)
141 {
142   if (flag_objc_exceptions
143       && !flag_objc_sjlj_exceptions)
144     {
145       warning_at (UNKNOWN_LOCATION, OPT_Wall,
146 		"%<-fobjc-sjlj-exceptions%> is the only supported exceptions "
147 		"system for %<-fnext-runtime%> with %<-fobjc-abi-version%> "
148 		"argument less than 2");
149     }
150 
151   rthooks->initialize = next_runtime_01_initialize;
152   rthooks->default_constant_string_class_name = DEF_CONSTANT_STRING_CLASS_NAME;
153   rthooks->tag_getclass = TAG_GETCLASS;
154   rthooks->super_superclassfield_ident = next_runtime_abi_01_super_superclassfield_id;
155 
156   rthooks->class_decl = next_runtime_abi_01_class_decl;
157   rthooks->metaclass_decl = next_runtime_abi_01_metaclass_decl;
158   rthooks->category_decl = next_runtime_abi_01_category_decl;
159   rthooks->protocol_decl = next_runtime_abi_01_protocol_decl;
160   rthooks->string_decl = next_runtime_abi_01_string_decl;
161 
162   rthooks->get_class_reference = next_runtime_abi_01_get_class_reference;
163   rthooks->build_selector_reference = next_runtime_abi_01_build_selector_reference;
164   rthooks->get_protocol_reference = next_runtime_abi_01_get_protocol_reference;
165   rthooks->build_ivar_reference = next_runtime_abi_01_build_ivar_ref;
166   rthooks->get_class_super_ref = next_runtime_abi_01_get_class_super_ref;
167   rthooks->get_category_super_ref = next_runtime_abi_01_get_category_super_ref;
168 
169   rthooks->receiver_is_class_object = next_runtime_abi_01_receiver_is_class_object;
170   rthooks->get_arg_type_list_base = next_runtime_abi_01_get_arg_type_list_base;
171   rthooks->build_objc_method_call = next_runtime_abi_01_build_objc_method_call;
172 
173   rthooks->setup_const_string_class_decl =
174 				next_runtime_abi_01_setup_const_string_class_decl;
175   rthooks->build_const_string_constructor =
176 				next_runtime_abi_01_build_const_string_constructor;
177 
178   rthooks->build_throw_stmt = build_throw_stmt;
179   rthooks->build_exc_ptr = objc_build_exc_ptr;
180   rthooks->begin_catch = begin_catch;
181   rthooks->finish_catch = finish_catch;
182   rthooks->finish_try_stmt = finish_try_stmt;
183 
184   rthooks->generate_metadata = objc_generate_v1_next_metadata;
185   return true;
186 }
187 
188 /* We need a way to convey what kind of meta-data are represented by a
189    given variable, since each type is expected (by the runtime) to be
190    found in a specific named section.  The solution must be usable
191    with LTO.
192 
193    The scheme used for NeXT ABI 0/1 (partial matching of variable
194    names) is not satisfactory for LTO & ABI-2.  We now tag ObjC
195    meta-data with identification attributes in the front end.  The
196    back-end may choose to act on these as it requires.  */
197 
198 static void
next_runtime_abi_01_init_metadata_attributes(void)199 next_runtime_abi_01_init_metadata_attributes (void)
200 {
201   if (!objc_meta)
202     objc_meta = get_identifier ("OBJC1META");
203 
204   if (!meta_base)
205     meta_base = get_identifier ("V1_BASE");
206 
207   meta_class = get_identifier ("V1_CLAS");
208   meta_metaclass = get_identifier ("V1_META");
209   meta_category = get_identifier ("V1_CATG");
210   meta_protocol = get_identifier ("V1_PROT");
211 
212   meta_clac_vars = get_identifier ("V1_CLCV");
213   meta_clai_vars = get_identifier ("V1_CLIV");
214 
215   meta_clac_meth = get_identifier ("V1_CLCM");
216   meta_clai_meth = get_identifier ("V1_CLIM");
217   meta_catc_meth = get_identifier ("V1_CACM");
218   meta_cati_meth = get_identifier ("V1_CAIM");
219   meta_proto_cls_meth = get_identifier ("V1_PCLM");
220   meta_proto_nst_meth = get_identifier ("V1_PNSM");
221 
222   meta_clas_prot = get_identifier ("V1_CLPR");
223   meta_catg_prot = get_identifier ("V1_CAPR");
224 
225   meta_class_reference = get_identifier ("V1_CLRF");
226   meta_proto_ref = get_identifier ("V1_PRFS");
227   meta_sel_refs = get_identifier ("V1_SRFS");
228 
229   meta_class_name = get_identifier ("V1_CLSN");
230   meta_meth_name = get_identifier ("V1_METN");
231   meta_meth_type = get_identifier ("V1_METT");
232   meta_prop_name_attr = get_identifier ("V1_STRG");
233 
234   meta_modules = get_identifier ("V1_MODU");
235   meta_symtab = get_identifier ("V1_SYMT");
236   meta_info = get_identifier ("V1_INFO");
237 
238   meta_proplist = get_identifier ("V1_PLST");
239   meta_protocol_extension = get_identifier ("V1_PEXT");
240   meta_class_extension = get_identifier ("V1_CEXT");
241 
242   meta_const_str = get_identifier ("V1_CSTR");
243 }
244 
245 static void build_v1_class_template (void);
246 static void build_v1_category_template (void);
247 static void build_v1_protocol_template (void);
248 
next_runtime_01_initialize(void)249 static void next_runtime_01_initialize (void)
250 {
251   tree type;
252 
253 #ifdef OBJCPLUS
254   /* For all NeXT objc ABIs -fobjc-call-cxx-cdtors is on by
255      default.  */
256   if (!OPTION_SET_P (flag_objc_call_cxx_cdtors))
257     global_options.x_flag_objc_call_cxx_cdtors = 1;
258 #endif
259 
260   /* Set up attributes to be attached to the meta-data so that they
261      will be placed in the correct sections.  */
262   next_runtime_abi_01_init_metadata_attributes ();
263 
264   if (flag_objc_abi >= 1)
265     objc_prop_list_ptr = build_pointer_type (xref_tag (RECORD_TYPE,
266 					     get_identifier ("_prop_list_t")));
267 
268  /* Declare type of selector-objects that represent an operation
269     name.  */
270   /* `struct objc_selector *' */
271   objc_selector_type = build_pointer_type (xref_tag (RECORD_TYPE,
272 					   get_identifier (TAG_SELECTOR)));
273 
274   /* SEL typedef.  */
275   type = lang_hooks.decls.pushdecl (build_decl (input_location,
276 						TYPE_DECL,
277 						objc_selector_name,
278 						objc_selector_type));
279   suppress_warning (type);
280 
281   build_v1_class_template ();
282   build_super_template ();
283   build_v1_protocol_template ();
284   build_v1_category_template ();
285 
286   /* NB: In order to call one of the ..._stret (struct-returning)
287      functions, the function *MUST* first be cast to a signature that
288      corresponds to the actual ObjC method being invoked.  This is
289      what is done by the build_objc_method_call() routine below.  */
290 
291   /* id objc_msgSend (id, SEL, ...); */
292   /* id objc_msgSendNonNil (id, SEL, ...); */
293   /* id objc_msgSend_stret (id, SEL, ...); */
294   /* id objc_msgSendNonNil_stret (id, SEL, ...); */
295   type = build_varargs_function_type_list (objc_object_type,
296 					   objc_object_type,
297 					   objc_selector_type,
298 					   NULL_TREE);
299 
300   umsg_decl = add_builtin_function (TAG_MSGSEND,
301 				    type, 0, NOT_BUILT_IN,
302 				    NULL, NULL_TREE);
303 
304   umsg_nonnil_decl = add_builtin_function (TAG_MSGSEND_NONNIL,
305 					   type, 0, NOT_BUILT_IN,
306 					    NULL, NULL_TREE);
307 
308   umsg_stret_decl = add_builtin_function (TAG_MSGSEND_STRET,
309 					  type, 0, NOT_BUILT_IN,
310 					  NULL, NULL_TREE);
311 
312   umsg_nonnil_stret_decl = add_builtin_function (TAG_MSGSEND_NONNIL_STRET,
313 						 type, 0, NOT_BUILT_IN,
314 						 NULL, NULL_TREE);
315 
316   /* These can throw, because the function that gets called can throw
317      in Obj-C++, or could itself call something that can throw even in
318      Obj-C.  */
319   TREE_NOTHROW (umsg_decl) = 0;
320   TREE_NOTHROW (umsg_nonnil_decl) = 0;
321   TREE_NOTHROW (umsg_stret_decl) = 0;
322   TREE_NOTHROW (umsg_nonnil_stret_decl) = 0;
323 
324  /* id objc_msgSend_Fast (id, SEL, ...)
325 	   __attribute__ ((hard_coded_address (OFFS_MSGSEND_FAST))); */
326 #ifdef OFFS_MSGSEND_FAST
327   umsg_fast_decl = add_builtin_function (TAG_MSGSEND_FAST,
328 					     type, 0, NOT_BUILT_IN,
329 					     NULL, NULL_TREE);
330   TREE_NOTHROW (umsg_fast_decl) = 0;
331   DECL_ATTRIBUTES (umsg_fast_decl)
332 	= tree_cons (get_identifier ("hard_coded_address"),
333 		     build_int_cst (NULL_TREE, OFFS_MSGSEND_FAST),
334 		     NULL_TREE);
335 #else
336   /* No direct dispatch available.  */
337   umsg_fast_decl = umsg_decl;
338 #endif
339 
340   /* id objc_msgSendSuper (struct objc_super *, SEL, ...); */
341   /* id objc_msgSendSuper_stret (struct objc_super *, SEL, ...); */
342   type = build_varargs_function_type_list (objc_object_type,
343                                             objc_super_type,
344                                             objc_selector_type,
345                                             NULL_TREE);
346   umsg_super_decl = add_builtin_function (TAG_MSGSENDSUPER,
347 					      type, 0, NOT_BUILT_IN,
348 					      NULL, NULL_TREE);
349   umsg_super_stret_decl = add_builtin_function (TAG_MSGSENDSUPER_STRET,
350 						    type, 0, NOT_BUILT_IN, 0,
351 						    NULL_TREE);
352   TREE_NOTHROW (umsg_super_decl) = 0;
353   TREE_NOTHROW (umsg_super_stret_decl) = 0;
354 
355   type = build_function_type_list (objc_object_type,
356                                    const_string_type_node,
357                                    NULL_TREE);
358 
359   /* id objc_getClass (const char *); */
360   objc_get_class_decl
361     = add_builtin_function (TAG_GETCLASS, type, 0, NOT_BUILT_IN,
362 			    NULL, NULL_TREE);
363 
364   /* id objc_getMetaClass (const char *); */
365   objc_get_meta_class_decl
366     = add_builtin_function (TAG_GETMETACLASS, type, 0, NOT_BUILT_IN, NULL, NULL_TREE);
367 
368   /* This is the type of all of the following functions
369      objc_copyStruct().  */
370   type = build_function_type_list (void_type_node,
371 				   ptr_type_node,
372 				   const_ptr_type_node,
373 				   ptrdiff_type_node,
374 				   boolean_type_node,
375 				   boolean_type_node,
376 				   NULL_TREE);
377   /* Declare the following function:
378 	 void
379          objc_copyStruct (void *destination, const void *source,
380 	                  ptrdiff_t size, BOOL is_atomic, BOOL has_strong); */
381   objc_copyStruct_decl = add_builtin_function ("objc_copyStruct",
382 						   type, 0, NOT_BUILT_IN,
383 						   NULL, NULL_TREE);
384   TREE_NOTHROW (objc_copyStruct_decl) = 0;
385   objc_getPropertyStruct_decl = NULL_TREE;
386   objc_setPropertyStruct_decl = NULL_TREE;
387 
388   build_next_objc_exception_stuff ();
389   if (flag_objc_exceptions && !flag_objc_sjlj_exceptions)
390     using_eh_for_cleanups ();
391   lang_hooks.eh_runtime_type = objc_eh_runtime_type;
392   lang_hooks.eh_personality = objc_eh_personality;
393 }
394 
395 /* --- templates --- */
396 
397 /* struct _objc_class
398    {
399      struct _objc_class *isa;
400      struct _objc_class *super_class;
401      char *name;
402      long version;
403      long info;
404      long instance_size;
405      struct _objc_ivar_list *ivars;
406      struct _objc_method_list *methods;
407      struct objc_cache *cache;
408      struct _objc_protocol_list *protocols;
409    #if ABI=1
410      const char *ivar_layout;
411      struct _objc_class_ext *ext;
412    #else
413      void *sel_id;
414      void *gc_object_type;
415     #endif
416    }; */
417 
418 /* The 'sel_id' & 'gc_object_type' fields are not used by the NeXT
419    runtime.  We generate them for ABI==0 to maintain backward binary
420    compatibility.  */
421 
422 static void
build_v1_class_template(void)423 build_v1_class_template (void)
424 {
425   tree ptype, decls, *chain = NULL;
426 
427   objc_class_template = objc_start_struct (get_identifier (UTAG_CLASS));
428 
429   /* struct _objc_class *isa; */
430   decls = add_field_decl (build_pointer_type (objc_class_template),
431 			  "isa", &chain);
432 
433   /* struct _objc_class *super_class; */
434   add_field_decl (build_pointer_type (objc_class_template),
435 		  "super_class", &chain);
436 
437   /* char *name; */
438   add_field_decl (string_type_node, "name", &chain);
439 
440   /* long version; */
441   add_field_decl (long_integer_type_node, "version", &chain);
442 
443   /* long info; */
444   add_field_decl (long_integer_type_node, "info", &chain);
445 
446   /* long instance_size; */
447   add_field_decl (long_integer_type_node, "instance_size", &chain);
448 
449   /* struct _objc_ivar_list *ivars; */
450   add_field_decl (objc_ivar_list_ptr,"ivars", &chain);
451 
452   /* struct _objc_method_list *methods; */
453   add_field_decl (objc_method_list_ptr, "methods", &chain);
454 
455   /* struct objc_cache *cache; */
456   ptype = build_pointer_type (xref_tag (RECORD_TYPE,
457 					    get_identifier ("objc_cache")));
458   add_field_decl (ptype, "cache", &chain);
459 
460   /* struct _objc_protocol **protocol_list; */
461   ptype = build_pointer_type (build_pointer_type
462 			      (xref_tag (RECORD_TYPE,
463 					 get_identifier (UTAG_PROTOCOL))));
464   add_field_decl (ptype, "protocol_list", &chain);
465 
466   if (flag_objc_abi >= 1)
467     {
468       /* const char *ivar_layout; */
469       add_field_decl (const_string_type_node, "ivar_layout", &chain);
470 
471       /* struct _objc_class_ext *ext; */
472       ptype = build_pointer_type (xref_tag (RECORD_TYPE,
473 					    get_identifier (UTAG_CLASS_EXT)));
474       add_field_decl (ptype, "ext", &chain);
475     }
476   else
477     {
478       /* void *sel_id; */
479       add_field_decl (build_pointer_type (void_type_node), "sel_id", &chain);
480       /* void *gc_object_type; */
481       add_field_decl (build_pointer_type (void_type_node), "gc_object_type",
482 		      &chain);
483     }
484 
485   objc_finish_struct (objc_class_template, decls);
486 }
487 
488 /* struct _objc_category
489    {
490      char *category_name;
491      char *class_name;
492      struct _objc_method_list *instance_methods;
493      struct _objc_method_list *class_methods;
494      struct _objc_protocol_list *protocols;
495    #if ABI=1
496      uint32_t size;	// sizeof (struct _objc_category)
497      struct _objc_property_list *instance_properties;  // category's own @property decl.
498    #endif
499    };   */
500 
501 static void
build_v1_category_template(void)502 build_v1_category_template (void)
503 {
504   tree ptype, decls, *chain = NULL;
505 
506   objc_category_template = objc_start_struct (get_identifier (UTAG_CATEGORY));
507 
508   /* char *category_name; */
509   decls = add_field_decl (string_type_node, "category_name", &chain);
510 
511   /* char *class_name; */
512   add_field_decl (string_type_node, "class_name", &chain);
513 
514   /* struct _objc_method_list *instance_methods; */
515   add_field_decl (objc_method_list_ptr, "instance_methods", &chain);
516 
517   /* struct _objc_method_list *class_methods; */
518   add_field_decl (objc_method_list_ptr, "class_methods", &chain);
519 
520   /* struct _objc_protocol **protocol_list; */
521   ptype = build_pointer_type (build_pointer_type (objc_protocol_template));
522   add_field_decl (ptype, "protocol_list", &chain);
523 
524   if (flag_objc_abi >= 1)
525     {
526       add_field_decl (integer_type_node, "size", &chain);
527 
528       /* struct _objc_property_list *instance_properties;
529          This field describes a category's @property declarations.
530          Properties from inherited protocols are not included.  */
531       ptype = build_pointer_type (xref_tag (RECORD_TYPE,
532 					    get_identifier (UTAG_PROPERTY_LIST)));
533       add_field_decl (ptype, "instance_properties", &chain);
534     }
535   objc_finish_struct (objc_category_template, decls);
536 }
537 
538 /* Begin code generation for protocols...
539    Modified for ObjC #1 extensions.  */
540 
541 /* struct _objc_protocol
542    {
543    #if ABI=1
544      struct _objc_protocol_extension *isa;
545    #else
546      struct _objc_class *isa;
547    #endif
548 
549      char *protocol_name;
550      struct _objc_protocol **protocol_list;
551      struct _objc__method_prototype_list *instance_methods;
552      struct _objc__method_prototype_list *class_methods;
553    }; */
554 
555 static void
build_v1_protocol_template(void)556 build_v1_protocol_template (void)
557 {
558   tree ptype, decls, *chain = NULL;
559 
560   objc_protocol_template = objc_start_struct (get_identifier (UTAG_PROTOCOL));
561 
562   if (flag_objc_abi >= 1)
563     /* struct _objc_protocol_extension *isa; */
564     ptype = build_pointer_type (xref_tag (RECORD_TYPE,
565 					  get_identifier (UTAG_PROTOCOL_EXT)));
566   else
567     /* struct _objc_class *isa; */
568     ptype = build_pointer_type (xref_tag (RECORD_TYPE,
569 					get_identifier (UTAG_CLASS)));
570 
571   decls = add_field_decl (ptype, "isa", &chain);
572 
573   /* char *protocol_name; */
574   add_field_decl (string_type_node, "protocol_name", &chain);
575 
576   /* struct _objc_protocol **protocol_list; */
577   ptype = build_pointer_type (build_pointer_type (objc_protocol_template));
578   add_field_decl (ptype, "protocol_list", &chain);
579 
580   /* struct _objc__method_prototype_list *instance_methods; */
581   add_field_decl (objc_method_proto_list_ptr, "instance_methods", &chain);
582 
583   /* struct _objc__method_prototype_list *class_methods; */
584   add_field_decl (objc_method_proto_list_ptr, "class_methods", &chain);
585 
586   objc_finish_struct (objc_protocol_template, decls);
587 }
588 
589 /* --- names, decls identifiers --- */
590 
591 static tree
next_runtime_abi_01_super_superclassfield_id(void)592 next_runtime_abi_01_super_superclassfield_id (void)
593 {
594   if (!super_superclassfield_id)
595     super_superclassfield_id = get_identifier ("super_class");
596   return super_superclassfield_id;
597 }
598 
599 static tree
next_runtime_abi_01_class_decl(tree klass)600 next_runtime_abi_01_class_decl (tree klass)
601 {
602   tree decl;
603   char buf[BUFSIZE];
604   snprintf (buf, BUFSIZE, "_OBJC_Class_%s",
605 	    IDENTIFIER_POINTER (CLASS_NAME (klass)));
606   decl = start_var_decl (objc_class_template, buf);
607   OBJCMETA (decl, objc_meta, meta_class);
608   return decl;
609 }
610 
611 static tree
next_runtime_abi_01_metaclass_decl(tree klass)612 next_runtime_abi_01_metaclass_decl (tree klass)
613 {
614   tree decl;
615   char buf[BUFSIZE];
616   snprintf (buf, BUFSIZE, "_OBJC_MetaClass_%s",
617 	    IDENTIFIER_POINTER (CLASS_NAME (klass)));
618   decl = start_var_decl (objc_class_template, buf);
619   OBJCMETA (decl, objc_meta, meta_metaclass);
620   return decl;
621 }
622 
623 static tree
next_runtime_abi_01_category_decl(tree klass)624 next_runtime_abi_01_category_decl (tree klass)
625 {
626   tree decl;
627   char buf[BUFSIZE];
628   snprintf (buf, BUFSIZE, "_OBJC_Category_%s_on_%s",
629 	    IDENTIFIER_POINTER (CLASS_SUPER_NAME (klass)),
630 	    IDENTIFIER_POINTER (CLASS_NAME (klass)));
631   decl = start_var_decl (objc_category_template, buf);
632   OBJCMETA (decl, objc_meta, meta_category);
633   return decl;
634 }
635 
636 static tree
next_runtime_abi_01_protocol_decl(tree p)637 next_runtime_abi_01_protocol_decl (tree p)
638 {
639   tree decl;
640   char buf[BUFSIZE];
641 
642   /* static struct _objc_protocol _OBJC_Protocol_<mumble>; */
643 
644   snprintf (buf, BUFSIZE, "_OBJC_Protocol_%s",
645 	    IDENTIFIER_POINTER (PROTOCOL_NAME (p)));
646   decl = start_var_decl (objc_protocol_template, buf);
647   OBJCMETA (decl, objc_meta, meta_protocol);
648   return decl;
649 }
650 
651 static tree
next_runtime_abi_01_string_decl(tree type,const char * name,string_section where)652 next_runtime_abi_01_string_decl (tree type, const char *name,  string_section where)
653 {
654   tree var = start_var_decl (type, name);
655   switch (where)
656     {
657       case class_names:
658 	OBJCMETA (var, objc_meta, meta_class_name);
659 	break;
660       case meth_var_names:
661 	OBJCMETA (var, objc_meta, meta_meth_name);
662 	break;
663       case meth_var_types:
664 	OBJCMETA (var, objc_meta, meta_meth_type);
665 	break;
666       case prop_names_attr:
667 	OBJCMETA (var, objc_meta, meta_prop_name_attr);
668 	break;
669       default:
670 	OBJCMETA (var, objc_meta, meta_base);
671 	break;
672     }
673   return var;
674 }
675 
676 /* --- entry --- */
677 
678 static GTY(()) int class_reference_idx;
679 
680 static tree
build_class_reference_decl(void)681 build_class_reference_decl (void)
682 {
683   tree decl;
684   char buf[BUFSIZE];
685 
686   sprintf (buf, "_OBJC_ClassRefs_%d", class_reference_idx++);
687   decl = start_var_decl (objc_class_type, buf);
688 
689   return decl;
690 }
691 
692 static tree
next_runtime_abi_01_get_class_reference(tree ident)693 next_runtime_abi_01_get_class_reference (tree ident)
694 {
695   if (!flag_zero_link)
696     {
697       tree *chain;
698       tree decl;
699 
700       for (chain = &cls_ref_chain; *chain; chain = &TREE_CHAIN (*chain))
701 	if (TREE_VALUE (*chain) == ident)
702 	  {
703 	    if (! TREE_PURPOSE (*chain))
704 	      TREE_PURPOSE (*chain) = build_class_reference_decl ();
705 
706 	    return TREE_PURPOSE (*chain);
707 	  }
708 
709       decl = build_class_reference_decl ();
710       *chain = tree_cons (decl, ident, NULL_TREE);
711       return decl;
712     }
713   else
714     {
715       tree params;
716 
717       add_class_reference (ident);
718 
719       params = build_tree_list (NULL_TREE,
720 				my_build_string_pointer
721 				(IDENTIFIER_LENGTH (ident) + 1,
722 				 IDENTIFIER_POINTER (ident)));
723 
724       return build_function_call (input_location, objc_get_class_decl, params);
725     }
726 }
727 
728 /* Used by build_function_type_for_method.  Append the types for
729    receiver & _cmd at the start of a method argument list to ARGTYPES.
730    CONTEXT is either METHOD_DEF or METHOD_REF, saying whether we are
731    trying to define a method or call one.  SUPERFLAG says this is for a
732    send to super.  METH may be NULL, in the case that there is no
733    prototype.  */
734 
735 static void
next_runtime_abi_01_get_arg_type_list_base(vec<tree,va_gc> ** argtypes,tree meth,int context,int superflag)736 next_runtime_abi_01_get_arg_type_list_base (vec<tree, va_gc> **argtypes,
737 					    tree meth, int context,
738 					    int superflag)
739 {
740   tree receiver_type;
741 
742   if (superflag)
743     receiver_type = objc_super_type;
744   else if (context == METHOD_DEF && TREE_CODE (meth) == INSTANCE_METHOD_DECL)
745     receiver_type = objc_instance_type;
746   else
747     receiver_type = objc_object_type;
748 
749   vec_safe_push (*argtypes, receiver_type);
750   /* Selector type - will eventually change to `int'.  */
751   vec_safe_push (*argtypes, objc_selector_type);
752 }
753 
754 static tree
next_runtime_abi_01_receiver_is_class_object(tree receiver)755 next_runtime_abi_01_receiver_is_class_object (tree receiver)
756 {
757   if (TREE_CODE (receiver) == VAR_DECL
758       && IS_CLASS (TREE_TYPE (receiver)))
759     {
760       /* The receiver is a variable created by build_class_reference_decl.  */
761       tree chain = cls_ref_chain ;
762       /* Look up the identifier in the relevant chain.  */
763       for (; chain; chain = TREE_CHAIN (chain))
764 	if (TREE_PURPOSE (chain) == receiver)
765 	  return TREE_VALUE (chain);
766     }
767   return NULL_TREE;
768 }
769 
770 static tree
build_selector_reference_decl(tree ident)771 build_selector_reference_decl (tree ident)
772 {
773   tree decl;
774   char *t, buf[BUFSIZE];
775 
776   snprintf (buf, BUFSIZE, "_OBJC_SelRef_%s", IDENTIFIER_POINTER (ident));
777   t = buf;
778   while (*t)
779     {
780       if (*t==':')
781         *t = '$'; /* Underscore would clash between foo:bar and foo_bar.  */
782       t++;
783     }
784   decl = start_var_decl (objc_selector_type, buf);
785   OBJCMETA (decl, objc_meta, meta_sel_refs);
786   return decl;
787 }
788 
789 static tree
next_runtime_abi_01_build_selector_reference(location_t loc ATTRIBUTE_UNUSED,tree ident,tree proto ATTRIBUTE_UNUSED)790 next_runtime_abi_01_build_selector_reference (location_t loc ATTRIBUTE_UNUSED,
791 					      tree ident,
792 					      tree proto ATTRIBUTE_UNUSED)
793 {
794   tree *chain = &sel_ref_chain;
795   tree expr;
796 
797   while (*chain)
798     {
799       if (TREE_VALUE (*chain) == ident)
800 	return TREE_PURPOSE (*chain);
801 
802       chain = &TREE_CHAIN (*chain);
803     }
804 
805   expr = build_selector_reference_decl (ident);
806 
807   *chain = tree_cons (expr, ident, NULL_TREE);
808 
809   return expr;
810 }
811 
812 /* Build a tree expression to send OBJECT the operation SELECTOR,
813    looking up the method on object LOOKUP_OBJECT (often same as OBJECT),
814    assuming the method has prototype METHOD_PROTOTYPE.
815    (That is an INSTANCE_METHOD_DECL or CLASS_METHOD_DECL.)
816    LOC is the location of the expression to build.
817    Use METHOD_PARAMS as list of args to pass to the method.
818    If SUPER_FLAG is nonzero, we look up the superclass's method.  */
819 
820 static tree
build_objc_method_call(location_t loc,int super_flag,tree method_prototype,tree lookup_object,tree selector,tree method_params)821 build_objc_method_call (location_t loc, int super_flag, tree method_prototype,
822 			tree lookup_object, tree selector,
823 			tree method_params)
824 {
825   tree sender, sender_cast, method, t;
826   tree rcv_p = (super_flag ? objc_super_type : objc_object_type);
827   vec<tree, va_gc> *parms;
828   unsigned nparm = (method_params ? list_length (method_params) : 0);
829 
830   /* If a prototype for the method to be called exists, then cast
831      the sender's return type and arguments to match that of the method.
832      Otherwise, leave sender as is.  */
833   tree ret_type
834     = (method_prototype
835        ? TREE_VALUE (TREE_TYPE (method_prototype))
836        : objc_object_type);
837   tree ftype = build_function_type_for_method (ret_type, method_prototype,
838 					       METHOD_REF, super_flag);
839 
840   if (method_prototype && METHOD_TYPE_ATTRIBUTES (method_prototype))
841     ftype = build_type_attribute_variant (ftype,
842 					  METHOD_TYPE_ATTRIBUTES
843 					  (method_prototype));
844 
845   sender_cast = build_pointer_type (ftype);
846 
847   lookup_object = build_c_cast (loc, rcv_p, lookup_object);
848 
849   /* Use SAVE_EXPR to avoid evaluating the receiver twice.  */
850   lookup_object = save_expr (lookup_object);
851 
852   /* Param list + 2 slots for object and selector.  */
853   vec_alloc (parms, nparm + 2);
854 
855   /* If we are returning a struct in memory, and the address
856      of that memory location is passed as a hidden first
857      argument, then change which messenger entry point this
858      expr will call.  NB: Note that sender_cast remains
859      unchanged (it already has a struct return type).  */
860   if (!targetm.calls.struct_value_rtx (0, 0)
861       && (TREE_CODE (ret_type) == RECORD_TYPE
862 	  || TREE_CODE (ret_type) == UNION_TYPE)
863       && targetm.calls.return_in_memory (ret_type, 0))
864     sender = (super_flag ? umsg_super_stret_decl
865 			 : flag_nil_receivers ? umsg_stret_decl
866 					      : umsg_nonnil_stret_decl);
867   else
868     sender = (super_flag ? umsg_super_decl
869 			 : (flag_nil_receivers  ? (flag_objc_direct_dispatch
870 							? umsg_fast_decl
871 							: umsg_decl)
872 						: umsg_nonnil_decl));
873   method = build_fold_addr_expr_loc (loc, sender);
874 
875   /* Pass the object to the method.  */
876   parms->quick_push (lookup_object);
877   /* Pass the selector to the method.  */
878   parms->quick_push (selector);
879   /* Now append the remainder of the parms.  */
880   if (nparm)
881     for (; method_params; method_params = TREE_CHAIN (method_params))
882       parms->quick_push (TREE_VALUE (method_params));
883 
884   /* Build an obj_type_ref, with the correct cast for the method call.  */
885   t = build3 (OBJ_TYPE_REF, sender_cast, method,
886 	      lookup_object, build_int_cst (TREE_TYPE (lookup_object), 0));
887   t = build_function_call_vec (loc, vNULL, t, parms, NULL);
888   vec_free (parms);
889   return t;
890 }
891 
892 static tree
next_runtime_abi_01_build_objc_method_call(location_t loc,tree method_prototype,tree receiver,tree rtype ATTRIBUTE_UNUSED,tree sel_name,tree method_params,int super)893 next_runtime_abi_01_build_objc_method_call (location_t loc,
894 					    tree method_prototype,
895 					    tree receiver,
896 					    tree rtype ATTRIBUTE_UNUSED,
897 					    tree sel_name,
898 					    tree method_params,
899 					    int super)
900 {
901   tree selector = next_runtime_abi_01_build_selector_reference (loc, sel_name,
902 								NULL_TREE);
903 
904   return build_objc_method_call (loc, super, method_prototype,
905 				 receiver, selector, method_params);
906 }
907 
908 static tree
next_runtime_abi_01_get_protocol_reference(location_t loc,tree p)909 next_runtime_abi_01_get_protocol_reference (location_t loc, tree p)
910 {
911   tree expr;
912 
913   if (!PROTOCOL_FORWARD_DECL (p))
914     PROTOCOL_FORWARD_DECL (p) = next_runtime_abi_01_protocol_decl (p);
915 
916   expr = build_unary_op (loc, ADDR_EXPR, PROTOCOL_FORWARD_DECL (p), 0);
917   return convert (objc_protocol_type, expr);
918 }
919 
920 /* For ABI 0/1 and IVAR is just a fixed offset in the class struct.  */
921 
922 static tree
next_runtime_abi_01_build_ivar_ref(location_t loc ATTRIBUTE_UNUSED,tree base,tree id)923 next_runtime_abi_01_build_ivar_ref (location_t loc ATTRIBUTE_UNUSED,
924 				   tree base, tree id)
925 {
926   return objc_build_component_ref (base, id);
927 }
928 
929 /* We build super class references as we need them (but keep them once
930    built for the sake of efficiency).  */
931 
932 static tree
next_runtime_abi_01_get_class_super_ref(location_t loc ATTRIBUTE_UNUSED,struct imp_entry * imp,bool inst_meth)933 next_runtime_abi_01_get_class_super_ref (location_t loc ATTRIBUTE_UNUSED,
934 					 struct imp_entry *imp, bool inst_meth)
935 {
936   if (inst_meth)
937     {
938       if (!ucls_super_ref)
939 	ucls_super_ref =
940 		objc_build_component_ref (imp->class_decl,
941 					  get_identifier ("super_class"));
942       return ucls_super_ref;
943     }
944   else
945     {
946       if (!uucls_super_ref)
947 	uucls_super_ref =
948 		objc_build_component_ref (imp->meta_decl,
949 					  get_identifier ("super_class"));
950       return uucls_super_ref;
951     }
952 }
953 
954 static tree
next_runtime_abi_01_get_category_super_ref(location_t loc ATTRIBUTE_UNUSED,struct imp_entry * imp,bool inst_meth)955 next_runtime_abi_01_get_category_super_ref (location_t loc ATTRIBUTE_UNUSED,
956 					   struct imp_entry *imp, bool inst_meth)
957 {
958   tree super_name = CLASS_SUPER_NAME (imp->imp_template);
959   tree super_class;
960 
961   if (!flag_zero_link)
962     {
963       super_class = objc_get_class_reference (super_name);
964 
965       if (!inst_meth)
966 
967 	/* If we are in a class method, we must retrieve the
968 	   _metaclass_ for the current class, pointed at by
969 	   the class's "isa" pointer.  The following assumes that
970 	   "isa" is the first ivar in a class (which it must be).  */
971 	   super_class =
972 		build_indirect_ref (input_location,
973 				    build_c_cast (input_location,
974 					build_pointer_type (objc_class_type),
975 					super_class),
976 				    RO_UNARY_STAR);
977       return super_class;
978     }
979 
980   /* else do it the slow way.  */
981   add_class_reference (super_name);
982   super_class = (inst_meth ? objc_get_class_decl : objc_get_meta_class_decl);
983   super_name = my_build_string_pointer (IDENTIFIER_LENGTH (super_name) + 1,
984 					IDENTIFIER_POINTER (super_name));
985   /* super_class = objc_get{Meta}Class("CLASS_SUPER_NAME"); */
986   return build_function_call (input_location,
987 			      super_class,
988 			      build_tree_list (NULL_TREE, super_name));
989 }
990 
991 static bool
next_runtime_abi_01_setup_const_string_class_decl(void)992 next_runtime_abi_01_setup_const_string_class_decl (void)
993 {
994   if (!constant_string_global_id)
995     {
996       /* Hopefully, this should not represent a serious limitation.  */
997       char buf[BUFSIZE];
998       snprintf (buf, BUFSIZE, "_%sClassReference", constant_string_class_name);
999       constant_string_global_id = get_identifier (buf);
1000     }
1001 
1002   string_class_decl = lookup_name (constant_string_global_id);
1003 
1004   return (string_class_decl != NULL_TREE);
1005 }
1006 
1007 static tree
next_runtime_abi_01_build_const_string_constructor(location_t loc,tree string,int length)1008 next_runtime_abi_01_build_const_string_constructor (location_t loc, tree string,
1009 						   int length)
1010 {
1011   tree constructor, fields, var;
1012   vec<constructor_elt, va_gc> *v = NULL;
1013 
1014   /* NeXT:   (NSConstantString *) & ((__builtin_ObjCString) { isa, string, length })   */
1015   fields = TYPE_FIELDS (internal_const_str_type);
1016   CONSTRUCTOR_APPEND_ELT (v, fields,
1017 			  build_unary_op (loc, ADDR_EXPR, string_class_decl, 0));
1018 
1019   fields = DECL_CHAIN (fields);
1020   CONSTRUCTOR_APPEND_ELT (v, fields,
1021 			  build_unary_op (loc, ADDR_EXPR, string, 1));
1022 
1023   /* ??? check if this should be long.  */
1024   fields = DECL_CHAIN (fields);
1025   CONSTRUCTOR_APPEND_ELT (v, fields, build_int_cst (NULL_TREE, length));
1026   constructor = objc_build_constructor (internal_const_str_type, v);
1027 
1028   var = build_decl (input_location, CONST_DECL, NULL, TREE_TYPE (constructor));
1029   DECL_INITIAL (var) = constructor;
1030   TREE_STATIC (var) = 1;
1031   DECL_CONTEXT (var) = NULL;
1032   OBJCMETA (var, objc_meta, meta_const_str);
1033   return var;
1034 }
1035 
1036 /* ---  metadata templates --- */
1037 
1038 /* This routine builds the following type:
1039    struct _prop_t {
1040      const char * const name;			// property name
1041      const char * const attributes;		// comma-delimited, encoded,
1042 						// property attributes
1043    };
1044 */
1045 
1046 static GTY(()) tree objc_v1_property_template;
1047 
1048 static tree
build_v1_property_template(void)1049 build_v1_property_template (void)
1050 {
1051   tree prop_record;
1052   tree decls, *chain = NULL;
1053 
1054   prop_record = objc_start_struct (get_identifier ("_prop_t"));
1055   /* const char * name */
1056   decls = add_field_decl (string_type_node, "name", &chain);
1057 
1058   /* const char * attribute */
1059   add_field_decl (string_type_node, "attribute", &chain);
1060 
1061   objc_finish_struct (prop_record, decls);
1062   return prop_record;
1063 }
1064 
1065 /* Build the following type:
1066 
1067   struct _objc_protocol_extension
1068     {
1069       uint32_t size;	// sizeof (struct _objc_protocol_extension)
1070       struct objc_method_list	*optional_instance_methods;
1071       struct objc_method_list   *optional_class_methods;
1072       struct objc_prop_list	*instance_properties;
1073     }
1074 */
1075 
1076 static GTY(()) tree objc_protocol_extension_template;
1077 
1078 static void
build_v1_objc_protocol_extension_template(void)1079 build_v1_objc_protocol_extension_template (void)
1080 {
1081   tree decls, *chain = NULL;
1082 
1083   objc_protocol_extension_template =
1084 	objc_start_struct (get_identifier (UTAG_PROTOCOL_EXT));
1085 
1086   /*  uint32_t size; */
1087   decls = add_field_decl (integer_type_node, "size", &chain);
1088 
1089   /* struct objc_method_list   *optional_instance_methods; */
1090   add_field_decl (objc_method_list_ptr, "optional_instance_methods", &chain);
1091 
1092   /* struct objc_method_list   *optional_class_methods; */
1093   add_field_decl (objc_method_list_ptr, "optional_class_methods", &chain);
1094 
1095   /* struct objc_prop_list     *instance_properties; */
1096   add_field_decl (objc_prop_list_ptr, "instance_properties", &chain);
1097 
1098   objc_finish_struct (objc_protocol_extension_template, decls);
1099 }
1100 
1101 /* This routine build following struct type:
1102    struct _objc_class_ext
1103      {
1104        uint32_t size;	// sizeof(struct _objc_class_ext)
1105        const char *weak_ivar_layout;
1106        struct _prop_list_t *properties;
1107      }
1108 */
1109 
1110 static GTY(()) tree objc_class_ext_template;
1111 
1112 static void
build_objc_class_ext_template(void)1113 build_objc_class_ext_template (void)
1114 {
1115   tree ptrt, decls, *chain = NULL;
1116 
1117   objc_class_ext_template = objc_start_struct (get_identifier (UTAG_CLASS_EXT));
1118 
1119   /* uint32_t size; */
1120   decls = add_field_decl (integer_type_node, "size", &chain);
1121 
1122   /* const char *weak_ivar_layout; */
1123   add_field_decl (const_string_type_node, "weak_ivar_layout", &chain);
1124 
1125   /* struct _prop_list_t *properties; */
1126   ptrt = build_pointer_type (xref_tag (RECORD_TYPE,
1127 			     get_identifier(UTAG_PROPERTY_LIST)));
1128   add_field_decl (ptrt, "properties", &chain);
1129 
1130   objc_finish_struct (objc_class_ext_template, decls);
1131 }
1132 
1133 static void
build_metadata_templates(void)1134 build_metadata_templates (void)
1135 {
1136 
1137   if (!objc_method_template)
1138     objc_method_template = build_method_template ();
1139 
1140 
1141 
1142 }
1143 
1144 /* --- emit metadata --- */
1145 
1146 static tree
generate_v1_meth_descriptor_table(tree chain,tree protocol,const char * prefix,tree attr)1147 generate_v1_meth_descriptor_table (tree chain, tree protocol,
1148 				   const char *prefix, tree attr)
1149 {
1150   tree method_list_template, initlist, decl;
1151   int size;
1152   vec<constructor_elt, va_gc> *v = NULL;
1153   char buf[BUFSIZE];
1154 
1155   if (!chain || !prefix)
1156     return NULL_TREE;
1157 
1158   if (!objc_method_prototype_template)
1159     objc_method_prototype_template = build_method_prototype_template ();
1160 
1161   size = list_length (chain);
1162   method_list_template =
1163 	build_method_prototype_list_template (objc_method_prototype_template,
1164 					      size);
1165   snprintf (buf, BUFSIZE, "%s_%s", prefix,
1166 	    IDENTIFIER_POINTER (PROTOCOL_NAME (protocol)));
1167 
1168   decl = start_var_decl (method_list_template, buf);
1169 
1170   CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, build_int_cst (NULL_TREE, size));
1171   initlist =
1172 	build_descriptor_table_initializer (objc_method_prototype_template,
1173 					    chain);
1174   CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, initlist);
1175   /* Get into the right section.  */
1176   OBJCMETA (decl, objc_meta, attr);
1177   finish_var_decl (decl, objc_build_constructor (method_list_template, v));
1178   return decl;
1179 }
1180 
1181 /* Build protocol ext =
1182    {size, opt_instance_meth, opt_class_meth, instance_props};
1183    or NULL_TREE if none are present.  */
1184 
1185 static tree
generate_v1_objc_protocol_extension(tree proto_interface,tree opt_instance_meth,tree opt_class_meth,tree instance_props)1186 generate_v1_objc_protocol_extension (tree proto_interface,
1187 				     tree opt_instance_meth,
1188 				     tree opt_class_meth,
1189 				     tree instance_props)
1190 {
1191   int size;
1192   location_t loc;
1193   vec<constructor_elt, va_gc> *v = NULL;
1194   tree decl, expr;
1195   char buf[BUFSIZE];
1196 
1197   /* If there are no extensions, then don't bother... */
1198   if (!opt_instance_meth && !opt_class_meth && !instance_props)
1199     return NULL_TREE;
1200 
1201   if (!objc_protocol_extension_template)
1202     build_v1_objc_protocol_extension_template ();
1203 
1204   /* uint32_t size */
1205   size = TREE_INT_CST_LOW (TYPE_SIZE_UNIT (objc_protocol_extension_template));
1206   CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, build_int_cst (NULL_TREE, size));
1207 
1208   /* Try for meaningful diagnostics.  */
1209   loc = DECL_SOURCE_LOCATION (PROTOCOL_FORWARD_DECL (proto_interface));
1210 
1211   /* struct objc_method_list *optional_instance_methods; */
1212   if (opt_instance_meth)
1213     expr = convert (objc_method_list_ptr,
1214 		    build_unary_op (loc, ADDR_EXPR, opt_instance_meth, 0));
1215   else
1216     expr = convert (objc_method_list_ptr, null_pointer_node);
1217 
1218   CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
1219 
1220   /* struct objc_method_list *optional_class_methods; */
1221   if (opt_class_meth)
1222     expr = convert (objc_method_list_ptr,
1223 		    build_unary_op (loc, ADDR_EXPR, opt_class_meth, 0));
1224   else
1225     expr = convert (objc_method_list_ptr, null_pointer_node);
1226 
1227   CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
1228   /* struct objc_prop_list *instance_properties; */
1229   if (instance_props)
1230       expr = convert (objc_prop_list_ptr,
1231 		      build_unary_op (loc, ADDR_EXPR, instance_props, 0));
1232   else
1233     expr = convert (objc_prop_list_ptr, null_pointer_node);
1234 
1235   CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
1236   snprintf (buf, BUFSIZE, "_OBJC_ProtocolExt_%s",
1237 	    IDENTIFIER_POINTER (PROTOCOL_NAME (proto_interface)));
1238 
1239   decl = start_var_decl (objc_protocol_extension_template, buf);
1240   expr = objc_build_constructor (TREE_TYPE (decl), v);
1241   OBJCMETA (decl, objc_meta, meta_protocol_extension);
1242   finish_var_decl (decl, expr);
1243   return decl;
1244 }
1245 
1246 /* This routine builds the following type:
1247    struct _prop_list_t {
1248      uint32_t entsize;			// sizeof (struct _prop_t)
1249      uint32_t prop_count;
1250      struct _prop_t prop_list [prop_count];
1251    }
1252 */
1253 
1254 static tree
build_v1_property_list_template(tree list_type,int size)1255 build_v1_property_list_template (tree list_type, int size)
1256 {
1257   tree property_list_t_record;
1258   tree array_type, decls, *chain = NULL;
1259 
1260   /* anonymous.  */
1261   property_list_t_record = objc_start_struct (NULL_TREE);
1262 
1263   /* uint32_t const entsize */
1264   decls = add_field_decl (integer_type_node, "entsize", &chain);
1265 
1266   /* int prop_count */
1267   add_field_decl (integer_type_node, "prop_count", &chain);
1268 
1269   /* struct _prop_t prop_list[]; */
1270   array_type = build_sized_array_type (list_type, size);
1271   add_field_decl (array_type, "prop_list", &chain);
1272 
1273   objc_finish_struct (property_list_t_record, decls);
1274   return property_list_t_record;
1275 }
1276 
1277 /* This routine builds the initializer list to initialize the
1278    'struct _prop_t prop_list[]'  field of 'struct _prop_list_t' meta-data. */
1279 
1280 static tree
build_v1_property_table_initializer(tree type,tree context)1281 build_v1_property_table_initializer (tree type, tree context)
1282 {
1283   tree x;
1284   vec<constructor_elt, va_gc> *inits = NULL;
1285 
1286   if (TREE_CODE (context) == PROTOCOL_INTERFACE_TYPE)
1287     x = CLASS_PROPERTY_DECL (context);
1288   else
1289     x = IMPL_PROPERTY_DECL (context);
1290 
1291   for (; x; x = TREE_CHAIN (x))
1292     {
1293       vec<constructor_elt, va_gc> *elemlist = NULL;
1294       tree attribute, name_ident = PROPERTY_NAME (x);
1295 
1296       CONSTRUCTOR_APPEND_ELT (elemlist, NULL_TREE,
1297 			      add_objc_string (name_ident, prop_names_attr));
1298 
1299       attribute = objc_v2_encode_prop_attr (x);
1300       CONSTRUCTOR_APPEND_ELT (elemlist, NULL_TREE,
1301 			      add_objc_string (attribute, prop_names_attr));
1302 
1303       CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE,
1304 			      objc_build_constructor (type, elemlist));
1305     }
1306 
1307   return objc_build_constructor (build_array_type (type, 0),inits);
1308 }
1309 
1310 /* This routine builds the 'struct _prop_list_t' variable declaration and
1311    initializes it with its initializer list. TYPE is 'struct _prop_list_t',
1312    NAME is the internal name of this variable, SIZE is number of properties
1313    for this class and LIST is the initializer list for its 'prop_list' field. */
1314 
1315 static tree
generate_v1_property_table(tree context,tree klass_ctxt)1316 generate_v1_property_table (tree context, tree klass_ctxt)
1317 {
1318   tree x, decl, initlist, property_list_template;
1319   bool is_proto = false;
1320   vec<constructor_elt, va_gc> *inits = NULL;
1321   int init_val, size = 0;
1322   char buf[BUFSIZE];
1323 
1324   if (context)
1325     {
1326       gcc_assert (TREE_CODE (context) == PROTOCOL_INTERFACE_TYPE);
1327       x = CLASS_PROPERTY_DECL (context);
1328       is_proto = true;
1329     }
1330   else
1331     x = IMPL_PROPERTY_DECL (klass_ctxt);
1332 
1333   for (; x; x = TREE_CHAIN (x))
1334     size++;
1335 
1336   if (size == 0)
1337     return NULL_TREE;
1338 
1339   if (!objc_v1_property_template)
1340     objc_v1_property_template = build_v1_property_template ();
1341 
1342   property_list_template =
1343 	build_v1_property_list_template (objc_v1_property_template,
1344 					 size);
1345   initlist = build_v1_property_table_initializer (objc_v1_property_template,
1346 						  is_proto ? context
1347 							   : klass_ctxt);
1348 
1349   init_val = TREE_INT_CST_LOW (TYPE_SIZE_UNIT (objc_v1_property_template));
1350   if (is_proto)
1351     snprintf (buf, BUFSIZE, "_OBJC_ProtocolPropList_%s",
1352 	      IDENTIFIER_POINTER (PROTOCOL_NAME (context)));
1353   else
1354     snprintf (buf, BUFSIZE, "_OBJC_ClassPropList_%s",
1355 	      IDENTIFIER_POINTER (CLASS_NAME (klass_ctxt)));
1356 
1357   decl = start_var_decl (property_list_template, buf);
1358   CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, build_int_cst (NULL_TREE, init_val));
1359   CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, build_int_cst (NULL_TREE, size));
1360   CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, initlist);
1361   x = objc_build_constructor (TREE_TYPE (decl), inits);
1362   OBJCMETA (decl, objc_meta, meta_proplist);
1363   finish_var_decl (decl, x);
1364   return decl;
1365 }
1366 
1367 static tree
generate_v1_protocol_list(tree i_or_p,tree klass_ctxt)1368 generate_v1_protocol_list (tree i_or_p, tree klass_ctxt)
1369 {
1370   tree array_type, ptype, refs_decl, lproto, e, plist, attr;
1371   int size = 0;
1372   vec<constructor_elt, va_gc> *v = NULL;
1373   char buf[BUFSIZE];
1374 
1375   switch (TREE_CODE (i_or_p))
1376     {
1377     case CLASS_INTERFACE_TYPE:
1378     case CATEGORY_INTERFACE_TYPE:
1379       plist = CLASS_PROTOCOL_LIST (i_or_p);
1380       break;
1381     case PROTOCOL_INTERFACE_TYPE:
1382       plist = PROTOCOL_LIST (i_or_p);
1383       break;
1384     default:
1385       gcc_unreachable ();
1386     }
1387 
1388   /* Compute size.  */
1389   for (lproto = plist; lproto; lproto = TREE_CHAIN (lproto))
1390     if (TREE_CODE (TREE_VALUE (lproto)) == PROTOCOL_INTERFACE_TYPE
1391 	&& PROTOCOL_FORWARD_DECL (TREE_VALUE (lproto)))
1392       size++;
1393 
1394   /* Build initializer.  */
1395   CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, build_int_cst (NULL_TREE, 0));
1396   e = build_int_cst (build_pointer_type (objc_protocol_template), size);
1397   CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, e);
1398 
1399   for (lproto = plist; lproto; lproto = TREE_CHAIN (lproto))
1400     {
1401       tree pval = TREE_VALUE (lproto);
1402 
1403       if (TREE_CODE (pval) == PROTOCOL_INTERFACE_TYPE
1404 	  && PROTOCOL_FORWARD_DECL (pval))
1405 	{
1406 	  tree fwref = PROTOCOL_FORWARD_DECL (pval);
1407 	  location_t loc = DECL_SOURCE_LOCATION (fwref) ;
1408 	  e = build_unary_op (loc, ADDR_EXPR, fwref, 0);
1409           CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, e);
1410 	}
1411     }
1412 
1413   /* static struct objc_protocol *refs[n]; */
1414   switch (TREE_CODE (i_or_p))
1415     {
1416     case PROTOCOL_INTERFACE_TYPE:
1417       snprintf (buf, BUFSIZE, "_OBJC_ProtocolRefs_%s",
1418 		IDENTIFIER_POINTER (PROTOCOL_NAME (i_or_p)));
1419       attr = meta_proto_ref;
1420       break;
1421     case CLASS_INTERFACE_TYPE:
1422       snprintf (buf, BUFSIZE, "_OBJC_ClassProtocols_%s",
1423 		IDENTIFIER_POINTER (CLASS_NAME (i_or_p)));
1424       attr = meta_clas_prot;
1425       break;
1426     case CATEGORY_INTERFACE_TYPE:
1427       snprintf (buf, BUFSIZE, "_OBJC_CategoryProtocols_%s_%s",
1428 		IDENTIFIER_POINTER (CLASS_NAME (klass_ctxt)),
1429 		IDENTIFIER_POINTER (CLASS_SUPER_NAME (klass_ctxt)));
1430       attr = meta_catg_prot;
1431       break;
1432     default:
1433       gcc_unreachable ();
1434     }
1435 
1436   ptype = build_pointer_type (objc_protocol_template);
1437   array_type = build_sized_array_type (ptype, size + 3);
1438   refs_decl = start_var_decl (array_type, buf);
1439 
1440   OBJCMETA (refs_decl, objc_meta, attr);
1441   finish_var_decl (refs_decl,
1442                    objc_build_constructor (TREE_TYPE (refs_decl), v));
1443 
1444   return refs_decl;
1445 }
1446 
1447 static tree
build_v1_protocol_initializer(tree type,tree protocol_name,tree protocol_list,tree inst_methods,tree class_methods,tree protocol_ext)1448 build_v1_protocol_initializer (tree type, tree protocol_name, tree protocol_list,
1449 			       tree inst_methods, tree class_methods,
1450 			       tree protocol_ext)
1451 {
1452   tree expr, ttyp;
1453   location_t loc;
1454   vec<constructor_elt, va_gc> *inits = NULL;
1455 
1456   if (!objc_protocol_extension_template)
1457     build_v1_objc_protocol_extension_template ();
1458 
1459   /* TODO: find a better representation of location from the inputs.  */
1460   loc = UNKNOWN_LOCATION;
1461   ttyp = build_pointer_type (objc_protocol_extension_template);
1462   /* Instead of jamming the protocol version number into the isa, we pass
1463      either a pointer to the protocol extension - or NULL.  */
1464   if (protocol_ext)
1465     expr = convert (ttyp, build_unary_op (loc, ADDR_EXPR, protocol_ext, 0));
1466   else
1467     expr = convert (ttyp, null_pointer_node);
1468 
1469   CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, expr);
1470   CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, protocol_name);
1471   CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, protocol_list);
1472 
1473   ttyp = objc_method_proto_list_ptr;
1474   if (inst_methods)
1475     expr = convert (ttyp, build_unary_op (loc, ADDR_EXPR, inst_methods, 0));
1476   else
1477     expr = convert (ttyp, null_pointer_node);
1478   CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, expr);
1479 
1480   if (class_methods)
1481     expr = convert (ttyp, build_unary_op (loc, ADDR_EXPR, class_methods, 0));
1482   else
1483     expr = convert (ttyp, null_pointer_node);
1484   CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, expr);
1485 
1486   return objc_build_constructor (type, inits);
1487 }
1488 
1489 /* An updated version of generate_protocols () that emit the protocol
1490    extension for ABI=1.  */
1491 
1492 /* For each protocol which was referenced either from a @protocol()
1493    expression, or because a class/category implements it (then a
1494    pointer to the protocol is stored in the struct describing the
1495    class/category), we create a statically allocated instance of the
1496    Protocol class.  The code is written in such a way as to generate
1497    as few Protocol objects as possible; we generate a unique Protocol
1498    instance for each protocol, and we don't generate a Protocol
1499    instance if the protocol is never referenced (either from a
1500    @protocol() or from a class/category implementation).  These
1501    statically allocated objects can be referred to via the static
1502    (that is, private to this module) symbols _OBJC_PROTOCOL_n.
1503 
1504    The statically allocated Protocol objects that we generate here
1505    need to be fixed up at runtime in order to be used: the 'isa'
1506    pointer of the objects need to be set up to point to the 'Protocol'
1507    class, as known at runtime.
1508 
1509    The NeXT runtime fixes up all protocols at program startup time,
1510    before main() is entered.  It uses a low-level trick to look up all
1511    those symbols, then loops on them and fixes them up.  */
1512 
1513 /* TODO: finish getting rid of passing stuff around in globals.  */
1514 
1515 static GTY(()) tree V1_Protocol_OPT_NST_METHODS_decl;
1516 static GTY(()) tree V1_Protocol_OPT_CLS_METHODS_decl;
1517 static GTY(()) tree V1_ProtocolExt_decl;
1518 static GTY(()) tree V1_Property_decl;
1519 
1520 static void
generate_v1_protocols(void)1521 generate_v1_protocols (void)
1522 {
1523   tree p;
1524 
1525   /* If a protocol was directly referenced, pull in indirect references.  */
1526   for (p = protocol_chain; p; p = TREE_CHAIN (p))
1527     if (PROTOCOL_FORWARD_DECL (p) && PROTOCOL_LIST (p))
1528       generate_protocol_references (PROTOCOL_LIST (p));
1529 
1530   for (p = protocol_chain; p; p = TREE_CHAIN (p))
1531     {
1532       tree decl, encoding, initlist, protocol_name_expr;
1533       tree refs_type, refs_decl, refs_expr;
1534       location_t loc;
1535       tree nst_methods = PROTOCOL_NST_METHODS (p);
1536       tree cls_methods = PROTOCOL_CLS_METHODS (p);
1537 
1538       /* If protocol wasn't referenced, don't generate any code.  */
1539       decl = PROTOCOL_FORWARD_DECL (p);
1540 
1541       if (!decl)
1542 	continue;
1543 
1544       /* Make sure we link in the Protocol class.  */
1545       add_class_reference (get_identifier (PROTOCOL_OBJECT_CLASS_NAME));
1546 
1547       while (nst_methods)
1548 	{
1549 	  if (! METHOD_ENCODING (nst_methods))
1550 	    {
1551 	      encoding = encode_method_prototype (nst_methods);
1552 	      METHOD_ENCODING (nst_methods) = encoding;
1553 	    }
1554 	  nst_methods = TREE_CHAIN (nst_methods);
1555 	}
1556 
1557       UOBJC_INSTANCE_METHODS_decl =
1558 	generate_v1_meth_descriptor_table (PROTOCOL_NST_METHODS (p), p,
1559 					   "_OBJC_ProtocolInstanceMethods",
1560 					   meta_proto_nst_meth);
1561 
1562       while (cls_methods)
1563 	{
1564 	  if (! METHOD_ENCODING (cls_methods))
1565 	    {
1566 	      encoding = encode_method_prototype (cls_methods);
1567 	      METHOD_ENCODING (cls_methods) = encoding;
1568 	    }
1569 
1570 	  cls_methods = TREE_CHAIN (cls_methods);
1571 	}
1572 
1573       UOBJC_CLASS_METHODS_decl =
1574 	generate_v1_meth_descriptor_table (PROTOCOL_CLS_METHODS (p), p,
1575 					   "_OBJC_ProtocolClassMethods",
1576 					   meta_proto_cls_meth);
1577 
1578       /* There should be no optional methods for ABI-0 - but we need to
1579          check all this here before the lists are made.  */
1580       nst_methods = PROTOCOL_OPTIONAL_NST_METHODS (p);
1581       while (nst_methods)
1582         {
1583           if (! METHOD_ENCODING (nst_methods))
1584             {
1585               encoding = encode_method_prototype (nst_methods);
1586               METHOD_ENCODING (nst_methods) = encoding;
1587             }
1588           nst_methods = TREE_CHAIN (nst_methods);
1589         }
1590 
1591       V1_Protocol_OPT_NST_METHODS_decl =
1592 	generate_v1_meth_descriptor_table (PROTOCOL_OPTIONAL_NST_METHODS (p), p,
1593 					   "_OBJC_OptionalProtocolInstanceMethods",
1594 					   meta_proto_nst_meth);
1595 
1596       cls_methods = PROTOCOL_OPTIONAL_CLS_METHODS (p);
1597       while (cls_methods)
1598         {
1599           if (! METHOD_ENCODING (cls_methods))
1600             {
1601               encoding = encode_method_prototype (cls_methods);
1602               METHOD_ENCODING (cls_methods) = encoding;
1603             }
1604 
1605           cls_methods = TREE_CHAIN (cls_methods);
1606         }
1607 
1608       V1_Protocol_OPT_CLS_METHODS_decl =
1609 	generate_v1_meth_descriptor_table (PROTOCOL_OPTIONAL_CLS_METHODS (p), p,
1610 					   "_OBJC_OptionalProtocolClassMethods",
1611 					   meta_proto_cls_meth);
1612 
1613       if (PROTOCOL_LIST (p))
1614 	refs_decl = generate_v1_protocol_list (p, objc_implementation_context);
1615       else
1616 	refs_decl = 0;
1617 
1618       /* static struct objc_protocol _OBJC_PROTOCOL_<mumble>; */
1619       protocol_name_expr = add_objc_string (PROTOCOL_NAME (p), class_names);
1620       /* TODO: more locations to be fixed up... */
1621       loc = UNKNOWN_LOCATION;
1622       refs_type =
1623 	build_pointer_type (build_pointer_type (objc_protocol_template));
1624       if (refs_decl)
1625 	refs_expr = convert (refs_type,
1626 			     build_unary_op (loc, ADDR_EXPR, refs_decl, 0));
1627       else
1628         refs_expr = convert (refs_type, null_pointer_node);
1629 
1630       if (flag_objc_abi < 1)
1631 	{
1632 	  /* Original ABI.  */
1633 	  initlist =
1634 		build_protocol_initializer (TREE_TYPE (decl),
1635 					    protocol_name_expr, refs_expr,
1636 					    UOBJC_INSTANCE_METHODS_decl,
1637 					    UOBJC_CLASS_METHODS_decl);
1638 	  finish_var_decl (decl, initlist);
1639           continue;
1640 	}
1641 
1642       /* else - V1 extensions.  */
1643 
1644       V1_Property_decl =
1645 		generate_v1_property_table (p, NULL_TREE);
1646 
1647       V1_ProtocolExt_decl =
1648 	generate_v1_objc_protocol_extension (p,
1649 					     V1_Protocol_OPT_NST_METHODS_decl,
1650 					     V1_Protocol_OPT_CLS_METHODS_decl,
1651 					     V1_Property_decl);
1652 
1653       initlist = build_v1_protocol_initializer (TREE_TYPE (decl),
1654 						protocol_name_expr, refs_expr,
1655 						UOBJC_INSTANCE_METHODS_decl,
1656 						UOBJC_CLASS_METHODS_decl,
1657 						V1_ProtocolExt_decl);
1658       finish_var_decl (decl, initlist);
1659     }
1660 }
1661 
1662 static tree
generate_dispatch_table(tree chain,const char * name,tree attr)1663 generate_dispatch_table (tree chain, const char *name, tree attr)
1664 {
1665   tree decl, method_list_template, initlist;
1666   vec<constructor_elt, va_gc> *v = NULL;
1667   int size;
1668 
1669   if (!chain || !name || !(size = list_length (chain)))
1670     return NULL_TREE;
1671 
1672   if (!objc_method_template)
1673     objc_method_template = build_method_template ();
1674 
1675   method_list_template = build_method_list_template (objc_method_template,
1676 						     size);
1677   initlist = build_dispatch_table_initializer (objc_method_template, chain);
1678 
1679   decl = start_var_decl (method_list_template, name);
1680 
1681   CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, integer_zero_node);
1682   CONSTRUCTOR_APPEND_ELT (v, NULL_TREE,
1683 			  build_int_cst (integer_type_node, size));
1684   CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, initlist);
1685 
1686   OBJCMETA (decl, objc_meta, attr);
1687   finish_var_decl (decl,
1688 		   objc_build_constructor (TREE_TYPE (decl), v));
1689 
1690   return decl;
1691 }
1692 
1693 /* Init a category.  */
1694 static tree
build_v1_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)1695 build_v1_category_initializer (tree type, tree cat_name, tree class_name,
1696 				tree inst_methods, tree class_methods,
1697 				tree protocol_list, tree property_list,
1698 				location_t loc)
1699 {
1700   tree expr, ltyp;
1701   vec<constructor_elt, va_gc> *v = NULL;
1702 
1703   CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, cat_name);
1704   CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, class_name);
1705 
1706   ltyp = objc_method_list_ptr;
1707   if (inst_methods)
1708     expr = convert (ltyp, build_unary_op (loc, ADDR_EXPR, inst_methods, 0));
1709   else
1710     expr = convert (ltyp, null_pointer_node);
1711   CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
1712 
1713   if (class_methods)
1714     expr = convert (ltyp, build_unary_op (loc, ADDR_EXPR, class_methods, 0));
1715   else
1716     expr = convert (ltyp, null_pointer_node);
1717   CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
1718 
1719   /* protocol_list = */
1720   ltyp = build_pointer_type (build_pointer_type (objc_protocol_template));
1721   if (protocol_list)
1722     expr = convert (ltyp, build_unary_op (loc, ADDR_EXPR, protocol_list, 0));
1723   else
1724     expr = convert (ltyp, null_pointer_node);
1725   CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
1726 
1727   if (flag_objc_abi >= 1)
1728     {
1729       int val = TREE_INT_CST_LOW (TYPE_SIZE_UNIT (objc_category_template));
1730       expr = build_int_cst (NULL_TREE, val);
1731       CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
1732       ltyp = objc_prop_list_ptr;
1733       if (property_list)
1734 	expr = convert (ltyp, build_unary_op (loc, ADDR_EXPR, property_list, 0));
1735       else
1736 	expr = convert (ltyp, null_pointer_node);
1737       CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
1738     }
1739 
1740   return objc_build_constructor (type, v);
1741 }
1742 
1743 /* static struct objc_category _OBJC_CATEGORY_<name> = { ... }; */
1744 /* TODO: get rid of passing stuff around in globals.  */
1745 static void
generate_v1_category(struct imp_entry * impent)1746 generate_v1_category (struct imp_entry *impent)
1747 {
1748   tree initlist, cat_name_expr, class_name_expr;
1749   tree protocol_decl, category, cat_decl;
1750   tree inst_methods = NULL_TREE, class_methods = NULL_TREE;
1751   tree cat = impent->imp_context;
1752   location_t loc;
1753   char buf[BUFSIZE];
1754 
1755   cat_decl = impent->class_decl;
1756   loc = DECL_SOURCE_LOCATION (cat_decl);
1757 
1758   add_class_reference (CLASS_NAME (cat));
1759   cat_name_expr = add_objc_string (CLASS_SUPER_NAME (cat), class_names);
1760   class_name_expr = add_objc_string (CLASS_NAME (cat), class_names);
1761 
1762   category = lookup_category (impent->imp_template, CLASS_SUPER_NAME (cat));
1763 
1764   if (category && CLASS_PROTOCOL_LIST (category))
1765     {
1766       generate_protocol_references (CLASS_PROTOCOL_LIST (category));
1767       protocol_decl = generate_v1_protocol_list (category, cat);
1768     }
1769   else
1770     protocol_decl = 0;
1771 
1772   if (flag_objc_abi >= 1)
1773     V1_Property_decl = generate_v1_property_table (NULL_TREE, cat);
1774   else
1775     V1_Property_decl = NULL_TREE;
1776 
1777   if (CLASS_NST_METHODS (cat))
1778     {
1779       snprintf (buf, BUFSIZE, "_OBJC_CategoryInstanceMethods_%s_%s",
1780 		IDENTIFIER_POINTER (CLASS_NAME (cat)),
1781 		IDENTIFIER_POINTER (CLASS_SUPER_NAME (cat)));
1782       inst_methods = generate_dispatch_table (CLASS_NST_METHODS (cat), buf,
1783 					      meta_cati_meth);
1784     }
1785 
1786   if (CLASS_CLS_METHODS (cat))
1787     {
1788       snprintf (buf, BUFSIZE, "_OBJC_CategoryClassMethods_%s_%s",
1789 		IDENTIFIER_POINTER (CLASS_NAME (cat)),
1790 		IDENTIFIER_POINTER (CLASS_SUPER_NAME (cat)));
1791       class_methods = generate_dispatch_table (CLASS_CLS_METHODS (cat), buf,
1792 					       meta_catc_meth);
1793     }
1794 
1795   initlist = build_v1_category_initializer (TREE_TYPE (cat_decl),
1796 					    cat_name_expr, class_name_expr,
1797 					    inst_methods, class_methods,
1798 					    protocol_decl, V1_Property_decl,
1799 					    loc);
1800 
1801   finish_var_decl (cat_decl, initlist);
1802   impent->class_decl = cat_decl;
1803 }
1804 
1805 /* This routine builds the class extension used by v1 NeXT.  */
1806 
1807 static tree
generate_objc_class_ext(tree property_list,tree context)1808 generate_objc_class_ext (tree property_list, tree context)
1809 {
1810   tree decl, expr, ltyp;
1811   tree weak_ivar_layout_tree;
1812   int size;
1813   location_t loc;
1814   vec<constructor_elt, va_gc> *v = NULL;
1815   char buf[BUFSIZE];
1816 
1817   /* TODO: pass the loc in or find it from args.  */
1818   loc = UNKNOWN_LOCATION;
1819 
1820   /* const char *weak_ivar_layout
1821      TODO: Figure the ivar layouts out... */
1822   weak_ivar_layout_tree = NULL_TREE;
1823 
1824   if (!property_list && !weak_ivar_layout_tree)
1825     return NULL_TREE;
1826 
1827   if (!objc_class_ext_template)
1828     build_objc_class_ext_template ();
1829 
1830   /* uint32_t size */
1831   size = TREE_INT_CST_LOW (TYPE_SIZE_UNIT (objc_class_ext_template));
1832   CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, build_int_cst (NULL_TREE, size));
1833 
1834   ltyp = const_string_type_node;
1835   if (weak_ivar_layout_tree)
1836     expr = convert (ltyp, weak_ivar_layout_tree);
1837   else
1838     expr = convert (ltyp, null_pointer_node);
1839   CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
1840 
1841   /* struct _prop_list_t *properties; */
1842   ltyp = objc_prop_list_ptr;
1843   if (property_list)
1844      expr = convert (ltyp, build_unary_op (loc, ADDR_EXPR, property_list, 0));
1845   else
1846     expr = convert (ltyp, null_pointer_node);
1847   CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
1848 
1849   snprintf (buf, BUFSIZE, "_OBJC_ClassExt_%s",
1850 	    IDENTIFIER_POINTER (CLASS_NAME (context)));
1851   decl = start_var_decl (objc_class_ext_template, buf);
1852   expr = objc_build_constructor (TREE_TYPE (decl), v);
1853   OBJCMETA (decl, objc_meta, meta_class_extension);
1854   finish_var_decl (decl, expr);
1855   return decl;
1856 }
1857 
1858 /* struct _objc_class {
1859      struct objc_class *isa;
1860      struct objc_class *super_class;
1861      char *name;
1862      long version;
1863      long info;
1864      long instance_size;
1865      struct objc_ivar_list *ivars;
1866      struct objc_method_list *methods;
1867      struct objc_cache *cache;
1868      struct objc_protocol_list *protocols;
1869   #if ABI >= 1
1870      const char *ivar_layout;
1871      struct _objc_class_ext *ext;
1872   #else
1873      void *sel_id;
1874      void *gc_object_type;
1875   #endif
1876    }; */
1877 
1878 static tree
build_v1_shared_structure_initializer(tree type,tree isa,tree super,tree name,tree size,int status,tree dispatch_table,tree ivar_list,tree protocol_list,tree class_ext)1879 build_v1_shared_structure_initializer (tree type, tree isa, tree super,
1880 				    tree name, tree size, int status,
1881 				    tree dispatch_table, tree ivar_list,
1882 				    tree protocol_list, tree class_ext)
1883 {
1884   tree expr, ltyp;
1885   location_t loc;
1886   vec<constructor_elt, va_gc> *v = NULL;
1887 
1888   /* TODO: fish the location out of the input data.  */
1889   loc = UNKNOWN_LOCATION;
1890 
1891   /* isa = */
1892   CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, isa);
1893 
1894   /* super_class = */
1895   CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, super);
1896 
1897   /* name = */
1898   CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, default_conversion (name));
1899 
1900   /* version = */
1901   CONSTRUCTOR_APPEND_ELT (v, NULL_TREE,
1902                           build_int_cst (long_integer_type_node, 0));
1903 
1904   /* info = */
1905   CONSTRUCTOR_APPEND_ELT (v, NULL_TREE,
1906                           build_int_cst (long_integer_type_node, status));
1907 
1908   /* instance_size = */
1909   CONSTRUCTOR_APPEND_ELT (v, NULL_TREE,
1910                           convert (long_integer_type_node, size));
1911 
1912   /* objc_ivar_list = */
1913   ltyp = objc_ivar_list_ptr;
1914   if (ivar_list)
1915     expr = convert (ltyp, build_unary_op (loc, ADDR_EXPR, ivar_list, 0));
1916   else
1917     expr = convert (ltyp, null_pointer_node);
1918   CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
1919 
1920   /* objc_method_list = */
1921   ltyp = objc_method_list_ptr;
1922   if (dispatch_table)
1923     expr = convert (ltyp, build_unary_op (loc, ADDR_EXPR, dispatch_table, 0));
1924   else
1925     expr = convert (ltyp, null_pointer_node);
1926   CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
1927 
1928   ltyp = build_pointer_type (xref_tag (RECORD_TYPE,
1929 					get_identifier ("objc_cache")));
1930   /* method_cache = */
1931   CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, convert (ltyp, null_pointer_node));
1932 
1933   /* protocol_list = */
1934   ltyp = build_pointer_type (build_pointer_type (objc_protocol_template));
1935   if (protocol_list)
1936     expr = convert (ltyp, build_unary_op (loc, ADDR_EXPR,  protocol_list, 0));
1937   else
1938     expr = convert (ltyp, null_pointer_node);
1939   CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
1940 
1941   if (flag_objc_abi >= 1)
1942     {
1943       /* TODO: figure out the ivar_layout stuff.  */
1944       expr = convert (const_string_type_node, null_pointer_node);
1945       CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
1946       if (!objc_class_ext_template)
1947 	build_objc_class_ext_template ();
1948       ltyp = build_pointer_type (objc_class_ext_template);
1949       if (class_ext)
1950 	expr = convert (ltyp, build_unary_op (loc, ADDR_EXPR, class_ext, 0));
1951       else
1952 	expr = convert (ltyp, null_pointer_node);
1953       CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
1954     }
1955   else
1956     {
1957       /* sel_id = NULL */
1958       CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, null_pointer_node);
1959 
1960       /* gc_object_type = NULL */
1961       CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, null_pointer_node);
1962     }
1963   return objc_build_constructor (type, v);
1964 }
1965 
1966 static tree
generate_ivars_list(tree chain,const char * name,tree attr)1967 generate_ivars_list (tree chain, const char *name, tree attr)
1968 {
1969   tree initlist, ivar_list_template, decl;
1970   int size;
1971   vec<constructor_elt, va_gc> *inits = NULL;
1972 
1973   if (!chain)
1974     return NULL_TREE;
1975 
1976   if (!objc_ivar_template)
1977     objc_ivar_template = build_ivar_template ();
1978 
1979   size = ivar_list_length (chain);
1980 
1981   generating_instance_variables = 1;
1982   ivar_list_template = build_ivar_list_template (objc_ivar_template, size);
1983   initlist = build_ivar_list_initializer (objc_ivar_template, chain);
1984   generating_instance_variables = 0;
1985 
1986   decl = start_var_decl (ivar_list_template, name);
1987 
1988   CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, build_int_cst (NULL_TREE, size));
1989   CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, initlist);
1990 
1991   OBJCMETA (decl, objc_meta, attr);
1992   finish_var_decl (decl,
1993 		   objc_build_constructor (TREE_TYPE (decl), inits));
1994 
1995   return decl;
1996 }
1997 
1998 /* static struct objc_class _OBJC_METACLASS_Foo={ ... };
1999    static struct objc_class _OBJC_CLASS_Foo={ ... }; */
2000 
2001 static void
generate_v1_class_structs(struct imp_entry * impent)2002 generate_v1_class_structs (struct imp_entry *impent)
2003 {
2004   tree name_expr, super_expr, root_expr, class_decl, meta_decl;
2005   tree my_root_id, my_super_id;
2006   tree cast_type, initlist, protocol_decl;
2007   tree class_ext_decl = NULL_TREE, props = NULL_TREE;
2008   tree inst_methods = NULL_TREE, class_methods = NULL_TREE;
2009   tree chain, inst_ivars = NULL_TREE, class_ivars = NULL_TREE;
2010   int cls_flags;
2011   location_t loc;
2012   char buf[BUFSIZE];
2013 
2014 /*  objc_implementation_context = impent->imp_context;
2015   implementation_template = impent->imp_template;*/
2016   class_decl = impent->class_decl;
2017   meta_decl = impent->meta_decl;
2018   cls_flags = impent->has_cxx_cdtors ? CLS_HAS_CXX_STRUCTORS : 0 ;
2019 
2020   loc = DECL_SOURCE_LOCATION (impent->class_decl);
2021 
2022   if (flag_objc_abi >= 1)
2023     {
2024       /* ABI=1 additions.  */
2025       props = generate_v1_property_table (NULL_TREE, impent->imp_context);
2026       class_ext_decl = generate_objc_class_ext (props, impent->imp_context);
2027     }
2028 
2029   my_super_id = CLASS_SUPER_NAME (impent->imp_template);
2030   if (my_super_id)
2031     {
2032       add_class_reference (my_super_id);
2033 
2034       /* Compute "my_root_id" - this is required for code generation.
2035          the "isa" for all meta class structures points to the root of
2036          the inheritance hierarchy (e.g. "__Object")...  */
2037       my_root_id = my_super_id;
2038       do
2039 	{
2040 	  tree my_root_int = lookup_interface (my_root_id);
2041 
2042 	  if (my_root_int && CLASS_SUPER_NAME (my_root_int))
2043 	    my_root_id = CLASS_SUPER_NAME (my_root_int);
2044 	  else
2045 	    break;
2046 	}
2047       while (1);
2048       super_expr = add_objc_string (my_super_id, class_names);
2049     }
2050   else
2051     {
2052       /* No super class.  */
2053       my_root_id = CLASS_NAME (impent->imp_template);
2054       super_expr = null_pointer_node;
2055     }
2056 
2057   /* Install class `isa' and `super' pointers at runtime.  */
2058   cast_type = build_pointer_type (objc_class_template);
2059   super_expr = build_c_cast (loc, cast_type, super_expr);
2060 
2061   root_expr = add_objc_string (my_root_id, class_names);
2062   root_expr = build_c_cast (loc, cast_type, root_expr);
2063 
2064   if (CLASS_PROTOCOL_LIST (impent->imp_template))
2065     {
2066       generate_protocol_references (CLASS_PROTOCOL_LIST (impent->imp_template));
2067       protocol_decl = generate_v1_protocol_list (impent->imp_template,
2068 						 impent->imp_context);
2069     }
2070   else
2071     protocol_decl = NULL_TREE;
2072 
2073   if (CLASS_CLS_METHODS (impent->imp_context))
2074     {
2075       snprintf (buf, BUFSIZE, "_OBJC_ClassMethods_%s",
2076 		IDENTIFIER_POINTER (CLASS_NAME (impent->imp_context)));
2077       class_methods = generate_dispatch_table (CLASS_CLS_METHODS (impent->imp_context),
2078 					       buf, meta_clac_meth);
2079     }
2080 
2081   if (CLASS_SUPER_NAME (impent->imp_template) == NULL_TREE
2082       && (chain = TYPE_FIELDS (objc_class_template)))
2083     {
2084       snprintf (buf, BUFSIZE, "_OBJC_ClassIvars_%s",
2085 		IDENTIFIER_POINTER (CLASS_NAME (impent->imp_context)));
2086       class_ivars = generate_ivars_list (chain, buf, meta_clac_vars);
2087     }
2088   /* TODO: get rid of hidden passing of stuff in globals.  */
2089   /* UOBJC_INSTANCE/CLASS_Variables_decl made in generate_ivarlists().  */
2090 
2091   name_expr = add_objc_string (CLASS_NAME (impent->imp_template), class_names);
2092 
2093   /* static struct objc_class _OBJC_METACLASS_Foo = { ... }; */
2094 
2095   initlist = build_v1_shared_structure_initializer
2096 		(TREE_TYPE (meta_decl),
2097 		root_expr, super_expr, name_expr,
2098 		convert (integer_type_node, TYPE_SIZE_UNIT (objc_class_template)),
2099 		CLS_META, class_methods, class_ivars,
2100 		protocol_decl, NULL_TREE);
2101 
2102   finish_var_decl (meta_decl, initlist);
2103   impent->meta_decl = meta_decl;
2104 
2105   /* static struct objc_class _OBJC_CLASS_Foo={ ... }; */
2106   if (CLASS_NST_METHODS (impent->imp_context))
2107     {
2108       snprintf (buf, BUFSIZE, "_OBJC_InstanceMethods_%s",
2109 		IDENTIFIER_POINTER (CLASS_NAME (impent->imp_context)));
2110       inst_methods = generate_dispatch_table (CLASS_NST_METHODS (impent->imp_context),
2111 					      buf, meta_clai_meth);
2112     }
2113 
2114   if ((chain = CLASS_IVARS (impent->imp_template)))
2115     {
2116       snprintf (buf, BUFSIZE, "_OBJC_InstanceIvars_%s",
2117 		IDENTIFIER_POINTER (CLASS_NAME (impent->imp_context)));
2118       inst_ivars = generate_ivars_list (chain, buf, meta_clai_vars);
2119     }
2120 
2121   initlist = build_v1_shared_structure_initializer
2122 		(TREE_TYPE (class_decl),
2123 		build_unary_op (loc, ADDR_EXPR, meta_decl, 0),
2124 		super_expr, name_expr,
2125 		convert (integer_type_node,
2126 			 TYPE_SIZE_UNIT (CLASS_STATIC_TEMPLATE (impent->imp_template))),
2127 		CLS_FACTORY | cls_flags, inst_methods, inst_ivars,
2128 		protocol_decl, class_ext_decl);
2129 
2130   finish_var_decl (class_decl, initlist);
2131   impent->class_decl = class_decl;
2132 }
2133 
2134 /* --- Output NeXT V1 Metadata --- */
2135 
2136 /* Create the initial value for the `defs' field of _objc_symtab.
2137    This is a CONSTRUCTOR.  */
2138 
2139 static tree
init_def_list(tree type)2140 init_def_list (tree type)
2141 {
2142   tree expr;
2143   location_t loc;
2144   struct imp_entry *impent;
2145   vec<constructor_elt, va_gc> *v = NULL;
2146 
2147   if (imp_count)
2148     for (impent = imp_list; impent; impent = impent->next)
2149       {
2150 	if (TREE_CODE (impent->imp_context) == CLASS_IMPLEMENTATION_TYPE)
2151 	  {
2152 	    loc = DECL_SOURCE_LOCATION (impent->class_decl);
2153 	    expr = build_unary_op (loc,
2154 				   ADDR_EXPR, impent->class_decl, 0);
2155 	    CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
2156 	  }
2157       }
2158 
2159   if (cat_count)
2160     for (impent = imp_list; impent; impent = impent->next)
2161       {
2162 	if (TREE_CODE (impent->imp_context) == CATEGORY_IMPLEMENTATION_TYPE)
2163 	  {
2164 	    loc = DECL_SOURCE_LOCATION (impent->class_decl);
2165 	    expr = build_unary_op (loc,
2166 				   ADDR_EXPR, impent->class_decl, 0);
2167 	    CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
2168 	  }
2169       }
2170 
2171   return objc_build_constructor (type, v);
2172 }
2173 
2174 /* Take care of defining and initializing _OBJC_SYMBOLS.  */
2175 
2176 /* Predefine the following data type:
2177 
2178    struct _objc_symtab
2179    {
2180      long sel_ref_cnt;
2181      SEL *refs;
2182      short cls_def_cnt;
2183      short cat_def_cnt;
2184      void *defs[cls_def_cnt + cat_def_cnt];
2185    }; */
2186 
2187 static void
build_objc_symtab_template(void)2188 build_objc_symtab_template (void)
2189 {
2190   tree fields, *chain = NULL;
2191 
2192   objc_symtab_template = objc_start_struct (get_identifier (UTAG_SYMTAB));
2193 
2194   /* long sel_ref_cnt; */
2195   fields = add_field_decl (long_integer_type_node, "sel_ref_cnt", &chain);
2196 
2197   /* SEL *refs; */
2198   add_field_decl (build_pointer_type (objc_selector_type), "refs", &chain);
2199 
2200   /* short cls_def_cnt; */
2201   add_field_decl (short_integer_type_node, "cls_def_cnt", &chain);
2202 
2203   /* short cat_def_cnt; */
2204   add_field_decl (short_integer_type_node, "cat_def_cnt", &chain);
2205 
2206   if (imp_count || cat_count)
2207     {
2208       /* void *defs[imp_count + cat_count (+ 1)]; */
2209       /* NB: The index is one less than the size of the array.  */
2210       int index = imp_count + cat_count;
2211       tree array_type = build_sized_array_type (ptr_type_node, index);
2212       add_field_decl (array_type, "defs", &chain);
2213     }
2214 
2215   objc_finish_struct (objc_symtab_template, fields);
2216 }
2217 /* Construct the initial value for all of _objc_symtab.  */
2218 
2219 static tree
init_objc_symtab(tree type)2220 init_objc_symtab (tree type)
2221 {
2222   vec<constructor_elt, va_gc> *v = NULL;
2223 
2224   /* sel_ref_cnt = { ..., 5, ... } */
2225 
2226   CONSTRUCTOR_APPEND_ELT (v, NULL_TREE,
2227 			  build_int_cst (long_integer_type_node, 0));
2228 
2229   /* refs = { ..., _OBJC_SELECTOR_TABLE, ... } */
2230 
2231   CONSTRUCTOR_APPEND_ELT (v, NULL_TREE,
2232 			  convert (build_pointer_type (objc_selector_type),
2233 							integer_zero_node));
2234 
2235   /* cls_def_cnt = { ..., 5, ... } */
2236 
2237   CONSTRUCTOR_APPEND_ELT (v, NULL_TREE,
2238 			  build_int_cst (short_integer_type_node, imp_count));
2239 
2240   /* cat_def_cnt = { ..., 5, ... } */
2241 
2242   CONSTRUCTOR_APPEND_ELT (v, NULL_TREE,
2243 			  build_int_cst (short_integer_type_node, cat_count));
2244 
2245   /* cls_def = { ..., { &Foo, &Bar, ...}, ... } */
2246 
2247   if (imp_count || cat_count)
2248     {
2249       tree field = TYPE_FIELDS (type);
2250       field = DECL_CHAIN (DECL_CHAIN (DECL_CHAIN (DECL_CHAIN (field))));
2251 
2252       CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, init_def_list (TREE_TYPE (field)));
2253     }
2254 
2255   return objc_build_constructor (type, v);
2256 }
2257 
2258 /* Create the declaration of _OBJC_SYMBOLS, with type `struct _objc_symtab'
2259    and initialized appropriately.  */
2260 
2261 static void
generate_objc_symtab_decl(void)2262 generate_objc_symtab_decl (void)
2263 {
2264   build_objc_symtab_template ();
2265   UOBJC_SYMBOLS_decl = start_var_decl (objc_symtab_template, "_OBJC_Symbols");
2266   /* Allow the runtime to mark meta-data such that it can be assigned to target
2267      specific sections by the back-end.  */
2268   OBJCMETA (UOBJC_SYMBOLS_decl, objc_meta, meta_symtab);
2269   finish_var_decl (UOBJC_SYMBOLS_decl,
2270 		   init_objc_symtab (TREE_TYPE (UOBJC_SYMBOLS_decl)));
2271 }
2272 
2273 /* Any target implementing NeXT ObjC m32 ABI has to ensure that objects
2274    refer to, and define, symbols that enforce linkage of classes into the
2275    executable image, preserving unix archive semantics.
2276 
2277    At present (4.8), the only targets implementing this are Darwin; these
2278    use top level asms to implement a scheme (see config/darwin-c.cc).  The
2279    latter method is a hack, but compatible with LTO see also PR48109 for
2280    further discussion and other possible methods.  */
2281 
2282 static void
handle_next_class_ref(tree chain ATTRIBUTE_UNUSED)2283 handle_next_class_ref (tree chain ATTRIBUTE_UNUSED)
2284 {
2285   if (targetcm.objc_declare_unresolved_class_reference)
2286     {
2287       const char *name = IDENTIFIER_POINTER (TREE_VALUE (chain));
2288       char *string = (char *) alloca (strlen (name) + 30);
2289       sprintf (string, ".objc_class_name_%s", name);
2290       targetcm.objc_declare_unresolved_class_reference (string);
2291     }
2292 }
2293 
2294 static void
handle_next_impent(struct imp_entry * impent ATTRIBUTE_UNUSED)2295 handle_next_impent (struct imp_entry *impent ATTRIBUTE_UNUSED)
2296 {
2297   if (targetcm.objc_declare_class_definition)
2298     {
2299       char buf[BUFSIZE];
2300 
2301       switch (TREE_CODE (impent->imp_context))
2302 	{
2303 	  case CLASS_IMPLEMENTATION_TYPE:
2304 	    snprintf (buf, BUFSIZE, ".objc_class_name_%s",
2305 		      IDENTIFIER_POINTER (CLASS_NAME (impent->imp_context)));
2306 	    break;
2307 	  case CATEGORY_IMPLEMENTATION_TYPE:
2308 	    snprintf (buf, BUFSIZE, "*.objc_category_name_%s_%s",
2309 		      IDENTIFIER_POINTER (CLASS_NAME (impent->imp_context)),
2310 		      IDENTIFIER_POINTER (CLASS_SUPER_NAME (impent->imp_context)));
2311 	    break;
2312 	  default:
2313 	    return;
2314 	}
2315       targetcm.objc_declare_class_definition (buf);
2316     }
2317 }
2318 
2319 static void
generate_classref_translation_entry(tree chain)2320 generate_classref_translation_entry (tree chain)
2321 {
2322   tree expr, decl, type;
2323 
2324   decl = TREE_PURPOSE (chain);
2325   type = TREE_TYPE (decl);
2326 
2327   expr = add_objc_string (TREE_VALUE (chain), class_names);
2328   expr = convert (type, expr); /* cast! */
2329 
2330   /* This is a class reference.  It is re-written by the runtime,
2331      but will be optimized away unless we force it.  */
2332   DECL_PRESERVE_P (decl) = 1;
2333   OBJCMETA (decl, objc_meta, meta_class_reference);
2334   finish_var_decl (decl, expr);
2335   return;
2336 }
2337 
2338 static void
objc_generate_v1_next_metadata(void)2339 objc_generate_v1_next_metadata (void)
2340 {
2341   struct imp_entry *impent;
2342   tree chain, attr;
2343   long vers;
2344 
2345   /* FIXME: Make sure that we generate no metadata if there is nothing
2346      to put into it.  */
2347 
2348   if (objc_static_instances)
2349     gcc_unreachable (); /* Not for NeXT */
2350 
2351   build_metadata_templates ();
2352   objc_implementation_context =
2353   implementation_template =
2354   UOBJC_CLASS_decl =
2355   UOBJC_METACLASS_decl = NULL_TREE;
2356 
2357   for (impent = imp_list; impent; impent = impent->next)
2358     {
2359 
2360       /* If -gen-decls is present, Dump the @interface of each class.
2361 	 TODO: Dump the classes in the  order they were found, rather than in
2362 	 reverse order as we are doing now.  */
2363       if (flag_gen_declaration)
2364 	dump_interface (gen_declaration_file, impent->imp_context);
2365 
2366       /* all of the following reference the string pool...  */
2367       if (TREE_CODE (impent->imp_context) == CLASS_IMPLEMENTATION_TYPE)
2368 	generate_v1_class_structs (impent);
2369       else
2370 	generate_v1_category (impent);
2371     }
2372 
2373   /* If we are using an array of selectors, we must always
2374      finish up the array decl even if no selectors were used.  */
2375   build_next_selector_translation_table ();
2376 
2377   if (protocol_chain)
2378     generate_v1_protocols ();
2379 
2380   /* Pass summary information to the runtime.  */
2381   if (imp_count || cat_count)
2382     generate_objc_symtab_decl ();
2383 
2384   vers = OBJC_VERSION;
2385   attr = build_tree_list (objc_meta, meta_modules);
2386   build_module_descriptor (vers, attr);
2387 
2388   /* Dump the class references.  This forces the appropriate classes
2389      to be linked into the executable image, preserving unix archive
2390      semantics.  */
2391   for (chain = cls_ref_chain; chain; chain = TREE_CHAIN (chain))
2392     {
2393       handle_next_class_ref (chain);
2394       if (TREE_PURPOSE (chain))
2395 	generate_classref_translation_entry (chain);
2396     }
2397 
2398   for (impent = imp_list; impent; impent = impent->next)
2399     handle_next_impent (impent);
2400 
2401   /* Emit the strings tables.  */
2402   generate_strings ();
2403 }
2404 
2405 /* --- exceptions stuff --- */
2406 
2407 /* Predefine the following data type:
2408 
2409    struct _objc_exception_data
2410    {
2411      int buf[OBJC_JBLEN];
2412      void *pointers[4];
2413    }; */
2414 
2415 /* The following yuckiness should prevent users from having to #include
2416    <setjmp.h> in their code... */
2417 
2418 /* Define to a harmless positive value so the below code doesn't die.  */
2419 #ifndef OBJC_JBLEN
2420 #define OBJC_JBLEN 18
2421 #endif
2422 
2423 static void
build_next_objc_exception_stuff(void)2424 build_next_objc_exception_stuff (void)
2425 {
2426   tree decls, temp_type, *chain = NULL;
2427 
2428   objc_exception_data_template
2429     = objc_start_struct (get_identifier (UTAG_EXCDATA));
2430 
2431   /* int buf[OBJC_JBLEN]; */
2432 
2433   temp_type = build_sized_array_type (integer_type_node, OBJC_JBLEN);
2434   decls = add_field_decl (temp_type, "buf", &chain);
2435 
2436   /* void *pointers[4]; */
2437 
2438   temp_type = build_sized_array_type (ptr_type_node, 4);
2439   add_field_decl (temp_type, "pointers", &chain);
2440 
2441   objc_finish_struct (objc_exception_data_template, decls);
2442 
2443   /* int _setjmp(...); */
2444   /* If the user includes <setjmp.h>, this shall be superseded by
2445      'int _setjmp(jmp_buf);' */
2446   temp_type = build_varargs_function_type_list (integer_type_node, NULL_TREE);
2447   objc_setjmp_decl
2448     = add_builtin_function (TAG_SETJMP, temp_type, 0, NOT_BUILT_IN, NULL, NULL_TREE);
2449 
2450   /* id objc_exception_extract(struct _objc_exception_data *); */
2451   temp_type
2452     = build_function_type_list (objc_object_type,
2453                                 build_pointer_type (objc_exception_data_template),
2454                                 NULL_TREE);
2455   objc_exception_extract_decl
2456     = add_builtin_function (TAG_EXCEPTIONEXTRACT, temp_type, 0, NOT_BUILT_IN, NULL,
2457 			    NULL_TREE);
2458   /* void objc_exception_try_enter(struct _objc_exception_data *); */
2459   /* void objc_exception_try_exit(struct _objc_exception_data *); */
2460   temp_type
2461     = build_function_type_list (void_type_node,
2462                                 build_pointer_type (objc_exception_data_template),
2463                                 NULL_TREE);
2464   objc_exception_try_enter_decl
2465     = add_builtin_function (TAG_EXCEPTIONTRYENTER, temp_type, 0, NOT_BUILT_IN, NULL,
2466 			    NULL_TREE);
2467   objc_exception_try_exit_decl
2468     = add_builtin_function (TAG_EXCEPTIONTRYEXIT, temp_type, 0, NOT_BUILT_IN, NULL,
2469 			    NULL_TREE);
2470 
2471   /* int objc_exception_match(id, id); */
2472   temp_type
2473     = build_function_type_list (integer_type_node,
2474                                 objc_object_type, objc_object_type, NULL_TREE);
2475   objc_exception_match_decl
2476     = add_builtin_function (TAG_EXCEPTIONMATCH, temp_type, 0, NOT_BUILT_IN, NULL,
2477 			    NULL_TREE);
2478 
2479   /* id objc_assign_ivar (id, id, unsigned int); */
2480   /* id objc_assign_ivar_Fast (id, id, unsigned int)
2481        __attribute__ ((hard_coded_address (OFFS_ASSIGNIVAR_FAST))); */
2482   temp_type
2483     = build_function_type_list (objc_object_type,
2484                                 objc_object_type,
2485                                 objc_object_type,
2486                                 unsigned_type_node,
2487                                 NULL_TREE);
2488   objc_assign_ivar_decl
2489     = add_builtin_function (TAG_ASSIGNIVAR, temp_type, 0, NOT_BUILT_IN,
2490 			    NULL, NULL_TREE);
2491 #ifdef OFFS_ASSIGNIVAR_FAST
2492   objc_assign_ivar_fast_decl
2493     = add_builtin_function (TAG_ASSIGNIVAR_FAST, temp_type, 0,
2494 			    NOT_BUILT_IN, NULL, NULL_TREE);
2495   DECL_ATTRIBUTES (objc_assign_ivar_fast_decl)
2496     = tree_cons (get_identifier ("hard_coded_address"),
2497 		 build_int_cst (NULL_TREE, OFFS_ASSIGNIVAR_FAST),
2498 		 NULL_TREE);
2499 #else
2500   /* Default to slower ivar method.  */
2501   objc_assign_ivar_fast_decl = objc_assign_ivar_decl;
2502 #endif
2503 
2504   /* id objc_assign_global (id, id *); */
2505   /* id objc_assign_strongCast (id, id *); */
2506   temp_type = build_function_type_list (objc_object_type,
2507                                         objc_object_type,
2508                                         build_pointer_type (objc_object_type),
2509                                         NULL_TREE);
2510   objc_assign_global_decl
2511 	= add_builtin_function (TAG_ASSIGNGLOBAL, temp_type, 0, NOT_BUILT_IN, NULL,
2512 				NULL_TREE);
2513   objc_assign_strong_cast_decl
2514 	= add_builtin_function (TAG_ASSIGNSTRONGCAST, temp_type, 0, NOT_BUILT_IN, NULL,
2515 				NULL_TREE);
2516 }
2517 
2518 /* --- NeXT V1 SJLJ Exceptions --- */
2519 
2520 /* Build "objc_exception_try_exit(&_stack)".  */
2521 
2522 static tree
next_sjlj_build_try_exit(struct objc_try_context ** ctcp)2523 next_sjlj_build_try_exit (struct objc_try_context **ctcp)
2524 {
2525   tree t;
2526   t = build_fold_addr_expr_loc (input_location, (*ctcp)->stack_decl);
2527   t = tree_cons (NULL, t, NULL);
2528   t = build_function_call (input_location,
2529 			   objc_exception_try_exit_decl, t);
2530   return t;
2531 }
2532 
2533 /* Build
2534 	objc_exception_try_enter (&_stack);
2535 	if (_setjmp(&_stack.buf))
2536 	  ;
2537 	else
2538 	  ;
2539    Return the COND_EXPR.  Note that the THEN and ELSE fields are left
2540    empty, ready for the caller to fill them in.  */
2541 
2542 static tree
next_sjlj_build_enter_and_setjmp(struct objc_try_context ** ctcp)2543 next_sjlj_build_enter_and_setjmp (struct objc_try_context **ctcp)
2544 {
2545   tree t, enter, sj, cond;
2546 
2547   t = build_fold_addr_expr_loc (input_location, (*ctcp)->stack_decl);
2548   t = tree_cons (NULL, t, NULL);
2549   enter = build_function_call (input_location,
2550 			       objc_exception_try_enter_decl, t);
2551 
2552   t = objc_build_component_ref ((*ctcp)->stack_decl,
2553 				get_identifier ("buf"));
2554   t = build_fold_addr_expr_loc (input_location, t);
2555 #ifdef OBJCPLUS
2556   /* Convert _setjmp argument to type that is expected.  */
2557   if (prototype_p (TREE_TYPE (objc_setjmp_decl)))
2558     t = convert (TREE_VALUE (TYPE_ARG_TYPES (TREE_TYPE (objc_setjmp_decl))), t);
2559   else
2560     t = convert (ptr_type_node, t);
2561 #else
2562   t = convert (ptr_type_node, t);
2563 #endif
2564   t = tree_cons (NULL, t, NULL);
2565   sj = build_function_call (input_location,
2566 			    objc_setjmp_decl, t);
2567 
2568   cond = build2 (COMPOUND_EXPR, TREE_TYPE (sj), enter, sj);
2569   cond = c_common_truthvalue_conversion (input_location, cond);
2570 
2571   return build3 (COND_EXPR, void_type_node, cond, NULL, NULL);
2572 }
2573 
2574 /* Build:
2575 
2576    DECL = objc_exception_extract(&_stack); */
2577 
2578 static tree
next_sjlj_build_exc_extract(struct objc_try_context ** ctcp,tree decl)2579 next_sjlj_build_exc_extract (struct objc_try_context **ctcp, tree decl)
2580 {
2581   tree t;
2582 
2583   t = build_fold_addr_expr_loc (input_location, (*ctcp)->stack_decl);
2584   t = tree_cons (NULL, t, NULL);
2585   t = build_function_call (input_location,
2586 			   objc_exception_extract_decl, t);
2587   t = convert (TREE_TYPE (decl), t);
2588   t = build2 (MODIFY_EXPR, void_type_node, decl, t);
2589 
2590   return t;
2591 }
2592 
2593 /* Build
2594 	if (objc_exception_match(obj_get_class(TYPE), _caught)
2595 	  BODY
2596 	else if (...)
2597 	  ...
2598 	else
2599 	  {
2600 	    _rethrow = _caught;
2601 	    objc_exception_try_exit(&_stack);
2602 	  }
2603    from the sequence of CATCH_EXPRs in the current try context.  */
2604 
2605 static tree
next_sjlj_build_catch_list(struct objc_try_context ** ctcp)2606 next_sjlj_build_catch_list (struct objc_try_context **ctcp)
2607 {
2608   tree_stmt_iterator i = tsi_start ((*ctcp)->catch_list);
2609   tree catch_seq, t;
2610   tree *last = &catch_seq;
2611   bool saw_id = false;
2612 
2613   for (; !tsi_end_p (i); tsi_next (&i))
2614     {
2615       tree stmt = tsi_stmt (i);
2616       tree type = CATCH_TYPES (stmt);
2617       tree body = CATCH_BODY (stmt);
2618 
2619       if (type != error_mark_node
2620 	  && objc_is_object_id (TREE_TYPE (type)))
2621 	{
2622 	  *last = body;
2623 	  saw_id = true;
2624 	  break;
2625 	}
2626       else
2627 	{
2628 	  tree args, cond;
2629 
2630 	  if (type == error_mark_node)
2631 	    cond = error_mark_node;
2632 	  else
2633 	    {
2634 	      args = tree_cons (NULL, (*ctcp)->caught_decl, NULL);
2635 	      t = objc_get_class_reference (OBJC_TYPE_NAME (TREE_TYPE (type)));
2636 	      args = tree_cons (NULL, t, args);
2637 	      t = build_function_call (input_location,
2638 				       objc_exception_match_decl, args);
2639 	      cond = c_common_truthvalue_conversion (input_location, t);
2640 	    }
2641 	  t = build3 (COND_EXPR, void_type_node, cond, body, NULL);
2642 	  SET_EXPR_LOCATION (t, EXPR_LOCATION (stmt));
2643 
2644 	  *last = t;
2645 	  last = &COND_EXPR_ELSE (t);
2646 	}
2647     }
2648 
2649   if (!saw_id)
2650     {
2651       t = build2 (MODIFY_EXPR, void_type_node, (*ctcp)->rethrow_decl,
2652 		  (*ctcp)->caught_decl);
2653       SET_EXPR_LOCATION (t, (*ctcp)->end_catch_locus);
2654       append_to_statement_list (t, last);
2655 
2656       t = next_sjlj_build_try_exit (ctcp);
2657       SET_EXPR_LOCATION (t, (*ctcp)->end_catch_locus);
2658       append_to_statement_list (t, last);
2659     }
2660 
2661   return catch_seq;
2662 }
2663 
2664 /* Build a complete @try-@catch-@finally block for legacy Darwin setjmp
2665    exception handling.  We aim to build:
2666 
2667 	{
2668 	  struct _objc_exception_data _stack;
2669 	  id _rethrow = 0;
2670 	  try
2671 	    {
2672 	      objc_exception_try_enter (&_stack);
2673 	      if (_setjmp(&_stack.buf))
2674 	        {
2675 		  id _caught = objc_exception_extract(&_stack);
2676 		  objc_exception_try_enter (&_stack);
2677 		  if (_setjmp(&_stack.buf))
2678 		    _rethrow = objc_exception_extract(&_stack);
2679 		  else
2680 		    CATCH-LIST
2681 	        }
2682 	      else
2683 		TRY-BLOCK
2684 	    }
2685 	  finally
2686 	    {
2687 	      if (!_rethrow)
2688 		objc_exception_try_exit(&_stack);
2689 	      FINALLY-BLOCK
2690 	      if (_rethrow)
2691 		objc_exception_throw(_rethrow);
2692 	    }
2693 	}
2694 
2695    If CATCH-LIST is empty, we can omit all of the block containing
2696    "_caught" except for the setting of _rethrow.  Note the use of
2697    a real TRY_FINALLY_EXPR here, which is not involved in EH per-se,
2698    but handles goto and other exits from the block.  */
2699 
2700 static tree
next_sjlj_build_try_catch_finally(struct objc_try_context ** ctcp)2701 next_sjlj_build_try_catch_finally (struct objc_try_context **ctcp)
2702 {
2703   tree rethrow_decl, stack_decl, t;
2704   tree catch_seq, try_fin, bind;
2705   struct objc_try_context *cur_try_context = *ctcp;
2706 
2707   /* Create the declarations involved.  */
2708   t = xref_tag (RECORD_TYPE, get_identifier (UTAG_EXCDATA));
2709   stack_decl = objc_create_temporary_var (t, NULL);
2710   cur_try_context->stack_decl = stack_decl;
2711 
2712   rethrow_decl = objc_create_temporary_var (objc_object_type, NULL);
2713   cur_try_context->rethrow_decl = rethrow_decl;
2714   TREE_CHAIN (rethrow_decl) = stack_decl;
2715 
2716   /* Build the outermost variable binding level.  */
2717   bind = build3 (BIND_EXPR, void_type_node, rethrow_decl, NULL, NULL);
2718   SET_EXPR_LOCATION (bind, cur_try_context->try_locus);
2719   TREE_SIDE_EFFECTS (bind) = 1;
2720 
2721   /* Initialize rethrow_decl.  */
2722   t = build2 (MODIFY_EXPR, void_type_node, rethrow_decl,
2723 	      convert (objc_object_type, null_pointer_node));
2724   SET_EXPR_LOCATION (t, cur_try_context->try_locus);
2725   append_to_statement_list (t, &BIND_EXPR_BODY (bind));
2726 
2727   /* Build the outermost TRY_FINALLY_EXPR.  */
2728   try_fin = build2 (TRY_FINALLY_EXPR, void_type_node, NULL, NULL);
2729   SET_EXPR_LOCATION (try_fin, cur_try_context->try_locus);
2730   TREE_SIDE_EFFECTS (try_fin) = 1;
2731   append_to_statement_list (try_fin, &BIND_EXPR_BODY (bind));
2732 
2733   /* Create the complete catch sequence.  */
2734   if (cur_try_context->catch_list)
2735     {
2736       tree caught_decl = objc_build_exc_ptr (ctcp);
2737       catch_seq = build_stmt (input_location, BIND_EXPR, caught_decl, NULL, NULL);
2738       TREE_SIDE_EFFECTS (catch_seq) = 1;
2739 
2740       t = next_sjlj_build_exc_extract (ctcp, caught_decl);
2741       append_to_statement_list (t, &BIND_EXPR_BODY (catch_seq));
2742 
2743       t = next_sjlj_build_enter_and_setjmp (ctcp);
2744       COND_EXPR_THEN (t) = next_sjlj_build_exc_extract (ctcp, rethrow_decl);
2745       COND_EXPR_ELSE (t) = next_sjlj_build_catch_list (ctcp);
2746       append_to_statement_list (t, &BIND_EXPR_BODY (catch_seq));
2747     }
2748   else
2749     catch_seq = next_sjlj_build_exc_extract (ctcp, rethrow_decl);
2750   SET_EXPR_LOCATION (catch_seq, cur_try_context->end_try_locus);
2751 
2752   /* Build the main register-and-try if statement.  */
2753   t = next_sjlj_build_enter_and_setjmp (ctcp);
2754   SET_EXPR_LOCATION (t, cur_try_context->try_locus);
2755   COND_EXPR_THEN (t) = catch_seq;
2756   COND_EXPR_ELSE (t) = cur_try_context->try_body;
2757   TREE_OPERAND (try_fin, 0) = t;
2758 
2759   /* Build the complete FINALLY statement list.  */
2760   t = next_sjlj_build_try_exit (ctcp);
2761   t = build_stmt (input_location, COND_EXPR,
2762 		  c_common_truthvalue_conversion
2763 		    (input_location, rethrow_decl),
2764 		  NULL, t);
2765   SET_EXPR_LOCATION (t, cur_try_context->finally_locus);
2766   append_to_statement_list (t, &TREE_OPERAND (try_fin, 1));
2767 
2768   append_to_statement_list (cur_try_context->finally_body,
2769 			    &TREE_OPERAND (try_fin, 1));
2770 
2771   t = tree_cons (NULL, rethrow_decl, NULL);
2772   t = build_function_call (input_location,
2773 			   objc_exception_throw_decl, t);
2774   t = build_stmt (input_location, COND_EXPR,
2775 		  c_common_truthvalue_conversion (input_location,
2776 						  rethrow_decl),
2777 		  t, NULL);
2778   SET_EXPR_LOCATION (t, cur_try_context->end_finally_locus);
2779   append_to_statement_list (t, &TREE_OPERAND (try_fin, 1));
2780 
2781   return bind;
2782 }
2783 
2784 /* We do not expect this to be used at the moment.
2785    If (a) it is possible to implement unwinder exceptions.
2786       (b) we do it... then it might be possibly useful.
2787 */
2788 static GTY(()) tree objc_eh_personality_decl;
2789 
2790 static tree
objc_eh_runtime_type(tree type)2791 objc_eh_runtime_type (tree type)
2792 {
2793   tree ident, eh_id, decl, str;
2794 
2795   gcc_unreachable ();
2796   if (type == error_mark_node)
2797     {
2798       /* Use 'ErrorMarkNode' as class name when error_mark_node is found
2799 	 to prevent an ICE.  Note that we know that the compiler will
2800 	 terminate with an error and this 'ErrorMarkNode' class name will
2801 	 never be actually used.  */
2802       ident = get_identifier ("ErrorMarkNode");
2803       goto make_err_class;
2804     }
2805 
2806   if (POINTER_TYPE_P (type) && objc_is_object_id (TREE_TYPE (type)))
2807     {
2808       ident = get_identifier ("id");
2809       goto make_err_class;
2810     }
2811 
2812   if (!POINTER_TYPE_P (type) || !TYPED_OBJECT (TREE_TYPE (type)))
2813     {
2814 #ifdef OBJCPLUS
2815       /* This routine is also called for c++'s catch clause; in which case,
2816 	 we use c++'s typeinfo decl. */
2817       return build_eh_type_type (type);
2818 #else
2819       error ("non-objective-c type %qT cannot be caught", type);
2820       ident = get_identifier ("ErrorMarkNode");
2821       goto make_err_class;
2822 #endif
2823     }
2824   else
2825     ident = OBJC_TYPE_NAME (TREE_TYPE (type));
2826 
2827 make_err_class:
2828   /* If this class was already referenced, then it will be output during
2829      meta-data emission, so we don't need to do it here.  */
2830   decl = get_objc_string_decl (ident, class_names);
2831   eh_id = add_objc_string (ident, class_names);
2832   if (!decl)
2833     {
2834       /* Not found ... so we need to build it - from the freshly-entered id.  */
2835       decl = get_objc_string_decl (ident, class_names);
2836       str = my_build_string (IDENTIFIER_LENGTH (ident) + 1,
2837 			     IDENTIFIER_POINTER (ident));
2838       /* We have to finalize this var here, because this might be called after
2839 	 all the other metadata strings have been emitted.  */
2840       finish_var_decl (decl, str);
2841     }
2842   return eh_id;
2843 }
2844 
2845 /* For NeXT ABI 0 and 1, the personality routines are just those of the
2846    underlying language.  */
2847 
2848 static tree
objc_eh_personality(void)2849 objc_eh_personality (void)
2850 {
2851   if (!objc_eh_personality_decl)
2852 #ifndef OBJCPLUS
2853     objc_eh_personality_decl = build_personality_function ("gcc");
2854 #else
2855     objc_eh_personality_decl = build_personality_function ("gxx");
2856 #endif
2857   return objc_eh_personality_decl;
2858 }
2859 
2860 /* --- interfaces --- */
2861 
2862 static tree
build_throw_stmt(location_t loc,tree throw_expr,bool rethrown ATTRIBUTE_UNUSED)2863 build_throw_stmt (location_t loc, tree throw_expr, bool rethrown ATTRIBUTE_UNUSED)
2864 {
2865   tree t;
2866   vec<tree, va_gc> *parms;
2867   vec_alloc (parms, 1);
2868   /* A throw is just a call to the runtime throw function with the
2869      object as a parameter.  */
2870   parms->quick_push (throw_expr);
2871   t = build_function_call_vec (loc, vNULL, objc_exception_throw_decl, parms,
2872 			       NULL);
2873   vec_free (parms);
2874   return add_stmt (t);
2875 }
2876 
2877 /* Build __builtin_eh_pointer, or the moral equivalent.  In the case
2878    of Darwin, we'll arrange for it to be initialized (and associated
2879    with a binding) later.  */
2880 
2881 static tree
objc_build_exc_ptr(struct objc_try_context ** cur_try_context)2882 objc_build_exc_ptr (struct objc_try_context **cur_try_context)
2883 {
2884   if (flag_objc_sjlj_exceptions)
2885     {
2886       tree var = (*cur_try_context)->caught_decl;
2887       if (!var)
2888 	{
2889 	  var = objc_create_temporary_var (objc_object_type, NULL);
2890 	  (*cur_try_context)->caught_decl = var;
2891 	}
2892       return var;
2893     }
2894   else
2895     {
2896       tree t;
2897       t = builtin_decl_explicit (BUILT_IN_EH_POINTER);
2898       t = build_call_expr (t, 1, integer_zero_node);
2899       return fold_convert (objc_object_type, t);
2900     }
2901 }
2902 
2903 static tree
begin_catch(struct objc_try_context ** cur_try_context,tree type,tree decl,tree compound,bool ellipsis ATTRIBUTE_UNUSED)2904 begin_catch (struct objc_try_context **cur_try_context, tree type,
2905 	     tree decl, tree compound, bool ellipsis ATTRIBUTE_UNUSED)
2906 {
2907   tree t;
2908   /* Record the data for the catch in the try context so that we can
2909      finalize it later.  We treat ellipsis the same way as catching
2910      with 'id xyz'.  */
2911   t = build_stmt (input_location, CATCH_EXPR, type, compound);
2912   (*cur_try_context)->current_catch = t;
2913 
2914   /* Initialize the decl from the EXC_PTR_EXPR we get from the runtime.  */
2915   t = objc_build_exc_ptr (cur_try_context);
2916   t = convert (TREE_TYPE (decl), t);
2917   return build2 (MODIFY_EXPR, void_type_node, decl, t);
2918 }
2919 
2920 static void
finish_catch(struct objc_try_context ** cur_try_context,tree current_catch)2921 finish_catch (struct objc_try_context **cur_try_context, tree current_catch)
2922 {
2923   append_to_statement_list (current_catch, &((*cur_try_context)->catch_list));
2924 }
2925 
2926 static tree
finish_try_stmt(struct objc_try_context ** cur_try_context)2927 finish_try_stmt (struct objc_try_context **cur_try_context)
2928 {
2929   tree stmt;
2930   struct objc_try_context *c = *cur_try_context;
2931   /* If we're doing Darwin setjmp exceptions, build the big nasty.  */
2932   if (flag_objc_sjlj_exceptions)
2933     {
2934       bool save = in_late_binary_op;
2935       in_late_binary_op = true;
2936       if (!c->finally_body)
2937 	{
2938 	  c->finally_locus = input_location;
2939 	  c->end_finally_locus = input_location;
2940 	}
2941       stmt = next_sjlj_build_try_catch_finally (cur_try_context);
2942       in_late_binary_op = save;
2943     }
2944   else
2945     /* This doesn't happen at the moment... but maybe one day... */
2946     {
2947       /* Otherwise, nest the CATCH inside a FINALLY.  */
2948       stmt = c->try_body;
2949       if (c->catch_list)
2950 	stmt = build_stmt (c->try_locus, TRY_CATCH_EXPR, stmt, c->catch_list);
2951       if (c->finally_body)
2952 	stmt = build_stmt (c->try_locus, TRY_FINALLY_EXPR, stmt, c->finally_body);
2953     }
2954   return stmt;
2955 }
2956 
2957 #include "gt-objc-objc-next-runtime-abi-01.h"
2958