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