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