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