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