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