OSDN Git Service

2014-04-07 Dominique d'Humieres <dominiq@lps.ens.fr>
[pf3gnuchains/gcc-fork.git] / gcc / objc / objc-next-runtime-abi-01.c
1 /* Next Runtime (ABI-0/1) private.
2    Copyright (C) 2011 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-tree.h"
33 #else
34 #include "c-tree.h"
35 #include "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,gc) **, tree,
127                                                         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,gc) **argtypes, tree meth,
734                                             int context, int superflag)
735 {
736   tree receiver_type;
737
738   if (superflag)
739     receiver_type = objc_super_type;
740   else if (context == METHOD_DEF && TREE_CODE (meth) == INSTANCE_METHOD_DECL)
741     receiver_type = objc_instance_type;
742   else
743     receiver_type = objc_object_type;
744
745   VEC_safe_push (tree, gc, *argtypes, receiver_type);
746   /* Selector type - will eventually change to `int'.  */
747   VEC_safe_push (tree, gc, *argtypes, objc_selector_type);
748 }
749
750 static tree
751 next_runtime_abi_01_receiver_is_class_object (tree receiver)
752 {
753   if (TREE_CODE (receiver) == VAR_DECL
754       && IS_CLASS (TREE_TYPE (receiver)))
755     {
756       /* The receiver is a variable created by build_class_reference_decl.  */
757       tree chain = cls_ref_chain ;
758       /* Look up the identifier in the relevant chain.  */
759       for (; chain; chain = TREE_CHAIN (chain))
760         if (TREE_PURPOSE (chain) == receiver)
761           return TREE_VALUE (chain);
762     }
763   return NULL_TREE;
764 }
765
766 static tree
767 build_selector_reference_decl (tree ident)
768 {
769   tree decl;
770   char *t, buf[BUFSIZE];
771
772   snprintf (buf, BUFSIZE, "_OBJC_SelRef_%s", IDENTIFIER_POINTER (ident));
773   t = buf;
774   while (*t)
775     {
776       if (*t==':')
777         *t = '$'; /* Underscore would clash between foo:bar and foo_bar.  */
778       t++;
779     }
780   decl = start_var_decl (objc_selector_type, buf);
781   OBJCMETA (decl, objc_meta, meta_sel_refs);
782   return decl;
783 }
784
785 static tree
786 next_runtime_abi_01_build_selector_reference (location_t loc ATTRIBUTE_UNUSED,
787                                               tree ident,
788                                               tree proto ATTRIBUTE_UNUSED)
789 {
790   tree *chain = &sel_ref_chain;
791   tree expr;
792
793   while (*chain)
794     {
795       if (TREE_VALUE (*chain) == ident)
796         return TREE_PURPOSE (*chain);
797
798       chain = &TREE_CHAIN (*chain);
799     }
800
801   expr = build_selector_reference_decl (ident);
802
803   *chain = tree_cons (expr, ident, NULL_TREE);
804
805   return expr;
806 }
807
808 /* Build a tree expression to send OBJECT the operation SELECTOR,
809    looking up the method on object LOOKUP_OBJECT (often same as OBJECT),
810    assuming the method has prototype METHOD_PROTOTYPE.
811    (That is an INSTANCE_METHOD_DECL or CLASS_METHOD_DECL.)
812    LOC is the location of the expression to build.
813    Use METHOD_PARAMS as list of args to pass to the method.
814    If SUPER_FLAG is nonzero, we look up the superclass's method.  */
815
816 static tree
817 build_objc_method_call (location_t loc, int super_flag, tree method_prototype,
818                         tree lookup_object, tree selector,
819                         tree method_params)
820 {
821   tree sender, sender_cast, method, t;
822   tree rcv_p = (super_flag ? objc_super_type : objc_object_type);
823   VEC(tree, gc) *parms;
824   unsigned nparm = (method_params ? list_length (method_params) : 0);
825
826   /* If a prototype for the method to be called exists, then cast
827      the sender's return type and arguments to match that of the method.
828      Otherwise, leave sender as is.  */
829   tree ret_type
830     = (method_prototype
831        ? TREE_VALUE (TREE_TYPE (method_prototype))
832        : objc_object_type);
833   tree ftype = build_function_type_for_method (ret_type, method_prototype,
834                                                METHOD_REF, super_flag);
835
836   if (method_prototype && METHOD_TYPE_ATTRIBUTES (method_prototype))
837     ftype = build_type_attribute_variant (ftype,
838                                           METHOD_TYPE_ATTRIBUTES
839                                           (method_prototype));
840
841   sender_cast = build_pointer_type (ftype);
842
843   lookup_object = build_c_cast (loc, rcv_p, lookup_object);
844
845   /* Use SAVE_EXPR to avoid evaluating the receiver twice.  */
846   lookup_object = save_expr (lookup_object);
847
848   /* Param list + 2 slots for object and selector.  */
849   parms = VEC_alloc (tree, gc, nparm + 2);
850
851   /* If we are returning a struct in memory, and the address
852      of that memory location is passed as a hidden first
853      argument, then change which messenger entry point this
854      expr will call.  NB: Note that sender_cast remains
855      unchanged (it already has a struct return type).  */
856   if (!targetm.calls.struct_value_rtx (0, 0)
857       && (TREE_CODE (ret_type) == RECORD_TYPE
858           || TREE_CODE (ret_type) == UNION_TYPE)
859       && targetm.calls.return_in_memory (ret_type, 0))
860     sender = (super_flag ? umsg_super_stret_decl
861                          : flag_nil_receivers ? umsg_stret_decl
862                                               : umsg_nonnil_stret_decl);
863   else
864     sender = (super_flag ? umsg_super_decl
865                          : (flag_nil_receivers  ? (flag_objc_direct_dispatch
866                                                         ? umsg_fast_decl
867                                                         : umsg_decl)
868                                                 : umsg_nonnil_decl));
869   method = build_fold_addr_expr_loc (loc, sender);
870
871   /* Pass the object to the method.  */
872   VEC_quick_push (tree, parms, lookup_object);
873   /* Pass the selector to the method.  */
874   VEC_quick_push (tree, parms, selector);
875   /* Now append the remainder of the parms.  */
876   if (nparm)
877     for (; method_params; method_params = TREE_CHAIN (method_params))
878       VEC_quick_push (tree, parms, TREE_VALUE (method_params));
879
880   /* Build an obj_type_ref, with the correct cast for the method call.  */
881   t = build3 (OBJ_TYPE_REF, sender_cast, method,
882                             lookup_object, size_zero_node);
883   t = build_function_call_vec (loc, t, parms, NULL);
884   VEC_free (tree, gc, parms);
885   return t;
886 }
887
888 static tree
889 next_runtime_abi_01_build_objc_method_call (location_t loc,
890                                             tree method_prototype,
891                                             tree receiver,
892                                             tree rtype ATTRIBUTE_UNUSED,
893                                             tree sel_name,
894                                             tree method_params,
895                                             int super)
896 {
897   tree selector = next_runtime_abi_01_build_selector_reference (loc, sel_name,
898                                                                 NULL_TREE);
899
900   return build_objc_method_call (loc, super, method_prototype,
901                                  receiver, selector, method_params);
902 }
903
904 static tree
905 next_runtime_abi_01_get_protocol_reference (location_t loc, tree p)
906 {
907   tree expr;
908
909   if (!PROTOCOL_FORWARD_DECL (p))
910     PROTOCOL_FORWARD_DECL (p) = next_runtime_abi_01_protocol_decl (p);
911
912   expr = build_unary_op (loc, ADDR_EXPR, PROTOCOL_FORWARD_DECL (p), 0);
913   return convert (objc_protocol_type, expr);
914 }
915
916 /* For ABI 0/1 and IVAR is just a fixed offset in the class struct.  */
917
918 static tree
919 next_runtime_abi_01_build_ivar_ref (location_t loc ATTRIBUTE_UNUSED,
920                                    tree base, tree id)
921 {
922   return objc_build_component_ref (base, id);
923 }
924
925 /* We build super class references as we need them (but keep them once
926    built for the sake of efficiency).  */
927
928 static tree
929 next_runtime_abi_01_get_class_super_ref (location_t loc ATTRIBUTE_UNUSED,
930                                          struct imp_entry *imp, bool inst_meth)
931 {
932   if (inst_meth)
933     {
934       if (!ucls_super_ref)
935         ucls_super_ref =
936                 objc_build_component_ref (imp->class_decl,
937                                           get_identifier ("super_class"));
938         return ucls_super_ref;
939     }
940   else
941     {
942       if (!uucls_super_ref)
943         uucls_super_ref =
944                 objc_build_component_ref (imp->meta_decl,
945                                           get_identifier ("super_class"));
946         return uucls_super_ref;
947     }
948 }
949
950 static tree
951 next_runtime_abi_01_get_category_super_ref (location_t loc ATTRIBUTE_UNUSED,
952                                            struct imp_entry *imp, bool inst_meth)
953 {
954   tree super_name = CLASS_SUPER_NAME (imp->imp_template);
955   tree super_class;
956
957   if (!flag_zero_link)
958     {
959       super_class = objc_get_class_reference (super_name);
960
961       if (!inst_meth)
962
963         /* If we are in a class method, we must retrieve the
964            _metaclass_ for the current class, pointed at by
965            the class's "isa" pointer.  The following assumes that
966            "isa" is the first ivar in a class (which it must be).  */
967            super_class =
968                 build_indirect_ref (input_location,
969                                     build_c_cast (input_location,
970                                         build_pointer_type (objc_class_type),
971                                         super_class),
972                                     RO_UNARY_STAR);
973       return super_class;
974     }
975
976   /* else do it the slow way.  */
977   add_class_reference (super_name);
978   super_class = (inst_meth ? objc_get_class_decl : objc_get_meta_class_decl);
979 /* assemble_external (super_class);*/
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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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 static void
2337 objc_generate_v1_next_metadata (void)
2338 {
2339   struct imp_entry *impent;
2340   tree chain, attr;
2341   long vers;
2342
2343   /* FIXME: Make sure that we generate no metadata if there is nothing
2344      to put into it.  */
2345
2346   if (objc_static_instances)
2347     gcc_unreachable (); /* Not for NeXT */
2348
2349   build_metadata_templates ();
2350   objc_implementation_context =
2351   implementation_template =
2352   UOBJC_CLASS_decl =
2353   UOBJC_METACLASS_decl = NULL_TREE;
2354
2355   for (impent = imp_list; impent; impent = impent->next)
2356     {
2357
2358       /* If -gen-decls is present, Dump the @interface of each class.
2359          TODO: Dump the classes in the  order they were found, rather than in
2360          reverse order as we are doing now.  */
2361       if (flag_gen_declaration)
2362         dump_interface (gen_declaration_file, impent->imp_context);
2363
2364       /* all of the following reference the string pool...  */
2365       if (TREE_CODE (impent->imp_context) == CLASS_IMPLEMENTATION_TYPE)
2366         generate_v1_class_structs (impent);
2367       else
2368         generate_v1_category (impent);
2369     }
2370
2371   /* If we are using an array of selectors, we must always
2372      finish up the array decl even if no selectors were used.  */
2373   build_next_selector_translation_table ();
2374
2375   if (protocol_chain)
2376     generate_v1_protocols ();
2377
2378   /* Pass summary information to the runtime.  */
2379   if (imp_count || cat_count)
2380     generate_objc_symtab_decl ();
2381
2382   vers = OBJC_VERSION;
2383   attr = build_tree_list (objc_meta, meta_modules);
2384   build_module_descriptor (vers, attr);
2385
2386   /* Dump the class references.  This forces the appropriate classes
2387      to be linked into the executable image, preserving unix archive
2388      semantics.  */
2389
2390   for (chain = cls_ref_chain; chain; chain = TREE_CHAIN (chain))
2391     {
2392       handle_next_class_ref (chain);
2393       if (TREE_PURPOSE (chain))
2394         generate_classref_translation_entry (chain);
2395     }
2396
2397   for (impent = imp_list; impent; impent = impent->next)
2398     handle_next_impent (impent);
2399
2400   /* Emit the strings tables.  */
2401   generate_strings ();
2402 }
2403
2404 /* --- exceptions stuff --- */
2405
2406 /* Predefine the following data type:
2407
2408    struct _objc_exception_data
2409    {
2410      int buf[OBJC_JBLEN];
2411      void *pointers[4];
2412    }; */
2413
2414 /* The following yuckiness should prevent users from having to #include
2415    <setjmp.h> in their code... */
2416
2417 /* Define to a harmless positive value so the below code doesn't die.  */
2418 #ifndef OBJC_JBLEN
2419 #define OBJC_JBLEN 18
2420 #endif
2421
2422 static void
2423 build_next_objc_exception_stuff (void)
2424 {
2425   tree decls, temp_type, *chain = NULL;
2426
2427   objc_exception_data_template
2428     = objc_start_struct (get_identifier (UTAG_EXCDATA));
2429
2430   /* int buf[OBJC_JBLEN]; */
2431
2432   temp_type = build_sized_array_type (integer_type_node, OBJC_JBLEN);
2433   decls = add_field_decl (temp_type, "buf", &chain);
2434
2435   /* void *pointers[4]; */
2436
2437   temp_type = build_sized_array_type (ptr_type_node, 4);
2438   add_field_decl (temp_type, "pointers", &chain);
2439
2440   objc_finish_struct (objc_exception_data_template, decls);
2441
2442   /* int _setjmp(...); */
2443   /* If the user includes <setjmp.h>, this shall be superseded by
2444      'int _setjmp(jmp_buf);' */
2445   temp_type = build_varargs_function_type_list (integer_type_node, NULL_TREE);
2446   objc_setjmp_decl
2447     = add_builtin_function (TAG_SETJMP, temp_type, 0, NOT_BUILT_IN, NULL, NULL_TREE);
2448
2449   /* id objc_exception_extract(struct _objc_exception_data *); */
2450   temp_type
2451     = build_function_type_list (objc_object_type,
2452                                 build_pointer_type (objc_exception_data_template),
2453                                 NULL_TREE);
2454   objc_exception_extract_decl
2455     = add_builtin_function (TAG_EXCEPTIONEXTRACT, temp_type, 0, NOT_BUILT_IN, NULL,
2456                             NULL_TREE);
2457   /* void objc_exception_try_enter(struct _objc_exception_data *); */
2458   /* void objc_exception_try_exit(struct _objc_exception_data *); */
2459   temp_type
2460     = build_function_type_list (void_type_node,
2461                                 build_pointer_type (objc_exception_data_template),
2462                                 NULL_TREE);
2463   objc_exception_try_enter_decl
2464     = add_builtin_function (TAG_EXCEPTIONTRYENTER, temp_type, 0, NOT_BUILT_IN, NULL,
2465                             NULL_TREE);
2466   objc_exception_try_exit_decl
2467     = add_builtin_function (TAG_EXCEPTIONTRYEXIT, temp_type, 0, NOT_BUILT_IN, NULL,
2468                             NULL_TREE);
2469
2470   /* int objc_exception_match(id, id); */
2471   temp_type
2472     = build_function_type_list (integer_type_node,
2473                                 objc_object_type, objc_object_type, NULL_TREE);
2474   objc_exception_match_decl
2475     = add_builtin_function (TAG_EXCEPTIONMATCH, temp_type, 0, NOT_BUILT_IN, NULL,
2476                             NULL_TREE);
2477
2478   /* id objc_assign_ivar (id, id, unsigned int); */
2479   /* id objc_assign_ivar_Fast (id, id, unsigned int)
2480        __attribute__ ((hard_coded_address (OFFS_ASSIGNIVAR_FAST))); */
2481   temp_type
2482     = build_function_type_list (objc_object_type,
2483                                 objc_object_type,
2484                                 objc_object_type,
2485                                 unsigned_type_node,
2486                                 NULL_TREE);
2487   objc_assign_ivar_decl
2488     = add_builtin_function (TAG_ASSIGNIVAR, temp_type, 0, NOT_BUILT_IN,
2489                             NULL, NULL_TREE);
2490 #ifdef OFFS_ASSIGNIVAR_FAST
2491   objc_assign_ivar_fast_decl
2492     = add_builtin_function (TAG_ASSIGNIVAR_FAST, temp_type, 0,
2493                             NOT_BUILT_IN, NULL, NULL_TREE);
2494   DECL_ATTRIBUTES (objc_assign_ivar_fast_decl)
2495     = tree_cons (get_identifier ("hard_coded_address"),
2496                  build_int_cst (NULL_TREE, OFFS_ASSIGNIVAR_FAST),
2497                  NULL_TREE);
2498 #else
2499   /* Default to slower ivar method.  */
2500   objc_assign_ivar_fast_decl = objc_assign_ivar_decl;
2501 #endif
2502
2503   /* id objc_assign_global (id, id *); */
2504   /* id objc_assign_strongCast (id, id *); */
2505   temp_type = build_function_type_list (objc_object_type,
2506                                         objc_object_type,
2507                                         build_pointer_type (objc_object_type),
2508                                         NULL_TREE);
2509   objc_assign_global_decl
2510         = add_builtin_function (TAG_ASSIGNGLOBAL, temp_type, 0, NOT_BUILT_IN, NULL,
2511                                 NULL_TREE);
2512   objc_assign_strong_cast_decl
2513         = add_builtin_function (TAG_ASSIGNSTRONGCAST, temp_type, 0, NOT_BUILT_IN, NULL,
2514                                 NULL_TREE);
2515 }
2516
2517 /* --- NeXT V1 SJLJ Exceptions --- */
2518
2519 /* Build "objc_exception_try_exit(&_stack)".  */
2520
2521 static tree
2522 next_sjlj_build_try_exit (struct objc_try_context **ctcp)
2523 {
2524   tree t;
2525   t = build_fold_addr_expr_loc (input_location, (*ctcp)->stack_decl);
2526   t = tree_cons (NULL, t, NULL);
2527   t = build_function_call (input_location,
2528                            objc_exception_try_exit_decl, t);
2529   return t;
2530 }
2531
2532 /* Build
2533         objc_exception_try_enter (&_stack);
2534         if (_setjmp(&_stack.buf))
2535           ;
2536         else
2537           ;
2538    Return the COND_EXPR.  Note that the THEN and ELSE fields are left
2539    empty, ready for the caller to fill them in.  */
2540
2541 static tree
2542 next_sjlj_build_enter_and_setjmp (struct objc_try_context **ctcp)
2543 {
2544   tree t, enter, sj, cond;
2545
2546   t = build_fold_addr_expr_loc (input_location, (*ctcp)->stack_decl);
2547   t = tree_cons (NULL, t, NULL);
2548   enter = build_function_call (input_location,
2549                                objc_exception_try_enter_decl, t);
2550
2551   t = objc_build_component_ref ((*ctcp)->stack_decl,
2552                                 get_identifier ("buf"));
2553   t = build_fold_addr_expr_loc (input_location, t);
2554 #ifdef OBJCPLUS
2555   /* Convert _setjmp argument to type that is expected.  */
2556   if (prototype_p (TREE_TYPE (objc_setjmp_decl)))
2557     t = convert (TREE_VALUE (TYPE_ARG_TYPES (TREE_TYPE (objc_setjmp_decl))), t);
2558   else
2559     t = convert (ptr_type_node, t);
2560 #else
2561   t = convert (ptr_type_node, t);
2562 #endif
2563   t = tree_cons (NULL, t, NULL);
2564   sj = build_function_call (input_location,
2565                             objc_setjmp_decl, t);
2566
2567   cond = build2 (COMPOUND_EXPR, TREE_TYPE (sj), enter, sj);
2568   cond = c_common_truthvalue_conversion (input_location, cond);
2569
2570   return build3 (COND_EXPR, void_type_node, cond, NULL, NULL);
2571 }
2572
2573 /* Build:
2574
2575    DECL = objc_exception_extract(&_stack); */
2576
2577 static tree
2578 next_sjlj_build_exc_extract (struct objc_try_context **ctcp, tree decl)
2579 {
2580   tree t;
2581
2582   t = build_fold_addr_expr_loc (input_location, (*ctcp)->stack_decl);
2583   t = tree_cons (NULL, t, NULL);
2584   t = build_function_call (input_location,
2585                            objc_exception_extract_decl, t);
2586   t = convert (TREE_TYPE (decl), t);
2587   t = build2 (MODIFY_EXPR, void_type_node, decl, t);
2588
2589   return t;
2590 }
2591
2592 /* Build
2593         if (objc_exception_match(obj_get_class(TYPE), _caught)
2594           BODY
2595         else if (...)
2596           ...
2597         else
2598           {
2599             _rethrow = _caught;
2600             objc_exception_try_exit(&_stack);
2601           }
2602    from the sequence of CATCH_EXPRs in the current try context.  */
2603
2604 static tree
2605 next_sjlj_build_catch_list (struct objc_try_context **ctcp)
2606 {
2607   tree_stmt_iterator i = tsi_start ((*ctcp)->catch_list);
2608   tree catch_seq, t;
2609   tree *last = &catch_seq;
2610   bool saw_id = false;
2611
2612   for (; !tsi_end_p (i); tsi_next (&i))
2613     {
2614       tree stmt = tsi_stmt (i);
2615       tree type = CATCH_TYPES (stmt);
2616       tree body = CATCH_BODY (stmt);
2617
2618       if (type != error_mark_node
2619           && objc_is_object_id (TREE_TYPE (type)))
2620         {
2621           *last = body;
2622           saw_id = true;
2623           break;
2624         }
2625       else
2626         {
2627           tree args, cond;
2628
2629           if (type == error_mark_node)
2630             cond = error_mark_node;
2631           else
2632             {
2633               args = tree_cons (NULL, (*ctcp)->caught_decl, NULL);
2634               t = objc_get_class_reference (OBJC_TYPE_NAME (TREE_TYPE (type)));
2635               args = tree_cons (NULL, t, args);
2636               t = build_function_call (input_location,
2637                                        objc_exception_match_decl, args);
2638               cond = c_common_truthvalue_conversion (input_location, t);
2639             }
2640           t = build3 (COND_EXPR, void_type_node, cond, body, NULL);
2641           SET_EXPR_LOCATION (t, EXPR_LOCATION (stmt));
2642
2643           *last = t;
2644           last = &COND_EXPR_ELSE (t);
2645         }
2646     }
2647
2648   if (!saw_id)
2649     {
2650       t = build2 (MODIFY_EXPR, void_type_node, (*ctcp)->rethrow_decl,
2651                   (*ctcp)->caught_decl);
2652       SET_EXPR_LOCATION (t, (*ctcp)->end_catch_locus);
2653       append_to_statement_list (t, last);
2654
2655       t = next_sjlj_build_try_exit (ctcp);
2656       SET_EXPR_LOCATION (t, (*ctcp)->end_catch_locus);
2657       append_to_statement_list (t, last);
2658     }
2659
2660   return catch_seq;
2661 }
2662
2663 /* Build a complete @try-@catch-@finally block for legacy Darwin setjmp
2664    exception handling.  We aim to build:
2665
2666         {
2667           struct _objc_exception_data _stack;
2668           id _rethrow = 0;
2669           try
2670             {
2671               objc_exception_try_enter (&_stack);
2672               if (_setjmp(&_stack.buf))
2673                 {
2674                   id _caught = objc_exception_extract(&_stack);
2675                   objc_exception_try_enter (&_stack);
2676                   if (_setjmp(&_stack.buf))
2677                     _rethrow = objc_exception_extract(&_stack);
2678                   else
2679                     CATCH-LIST
2680                 }
2681               else
2682                 TRY-BLOCK
2683             }
2684           finally
2685             {
2686               if (!_rethrow)
2687                 objc_exception_try_exit(&_stack);
2688               FINALLY-BLOCK
2689               if (_rethrow)
2690                 objc_exception_throw(_rethrow);
2691             }
2692         }
2693
2694    If CATCH-LIST is empty, we can omit all of the block containing
2695    "_caught" except for the setting of _rethrow.  Note the use of
2696    a real TRY_FINALLY_EXPR here, which is not involved in EH per-se,
2697    but handles goto and other exits from the block.  */
2698
2699 static tree
2700 next_sjlj_build_try_catch_finally (struct objc_try_context **ctcp)
2701 {
2702   tree rethrow_decl, stack_decl, t;
2703   tree catch_seq, try_fin, bind;
2704   struct objc_try_context *cur_try_context = *ctcp;
2705
2706   /* Create the declarations involved.  */
2707   t = xref_tag (RECORD_TYPE, get_identifier (UTAG_EXCDATA));
2708   stack_decl = objc_create_temporary_var (t, NULL);
2709   cur_try_context->stack_decl = stack_decl;
2710
2711   rethrow_decl = objc_create_temporary_var (objc_object_type, NULL);
2712   cur_try_context->rethrow_decl = rethrow_decl;
2713   TREE_CHAIN (rethrow_decl) = stack_decl;
2714
2715   /* Build the outermost variable binding level.  */
2716   bind = build3 (BIND_EXPR, void_type_node, rethrow_decl, NULL, NULL);
2717   SET_EXPR_LOCATION (bind, cur_try_context->try_locus);
2718   TREE_SIDE_EFFECTS (bind) = 1;
2719
2720   /* Initialize rethrow_decl.  */
2721   t = build2 (MODIFY_EXPR, void_type_node, rethrow_decl,
2722               convert (objc_object_type, null_pointer_node));
2723   SET_EXPR_LOCATION (t, cur_try_context->try_locus);
2724   append_to_statement_list (t, &BIND_EXPR_BODY (bind));
2725
2726   /* Build the outermost TRY_FINALLY_EXPR.  */
2727   try_fin = build2 (TRY_FINALLY_EXPR, void_type_node, NULL, NULL);
2728   SET_EXPR_LOCATION (try_fin, cur_try_context->try_locus);
2729   TREE_SIDE_EFFECTS (try_fin) = 1;
2730   append_to_statement_list (try_fin, &BIND_EXPR_BODY (bind));
2731
2732   /* Create the complete catch sequence.  */
2733   if (cur_try_context->catch_list)
2734     {
2735       tree caught_decl = objc_build_exc_ptr (ctcp);
2736       catch_seq = build_stmt (input_location, BIND_EXPR, caught_decl, NULL, NULL);
2737       TREE_SIDE_EFFECTS (catch_seq) = 1;
2738
2739       t = next_sjlj_build_exc_extract (ctcp, caught_decl);
2740       append_to_statement_list (t, &BIND_EXPR_BODY (catch_seq));
2741
2742       t = next_sjlj_build_enter_and_setjmp (ctcp);
2743       COND_EXPR_THEN (t) = next_sjlj_build_exc_extract (ctcp, rethrow_decl);
2744       COND_EXPR_ELSE (t) = next_sjlj_build_catch_list (ctcp);
2745       append_to_statement_list (t, &BIND_EXPR_BODY (catch_seq));
2746     }
2747   else
2748     catch_seq = next_sjlj_build_exc_extract (ctcp, rethrow_decl);
2749   SET_EXPR_LOCATION (catch_seq, cur_try_context->end_try_locus);
2750
2751   /* Build the main register-and-try if statement.  */
2752   t = next_sjlj_build_enter_and_setjmp (ctcp);
2753   SET_EXPR_LOCATION (t, cur_try_context->try_locus);
2754   COND_EXPR_THEN (t) = catch_seq;
2755   COND_EXPR_ELSE (t) = cur_try_context->try_body;
2756   TREE_OPERAND (try_fin, 0) = t;
2757
2758   /* Build the complete FINALLY statement list.  */
2759   t = next_sjlj_build_try_exit (ctcp);
2760   t = build_stmt (input_location, COND_EXPR,
2761                   c_common_truthvalue_conversion
2762                     (input_location, rethrow_decl),
2763                   NULL, t);
2764   SET_EXPR_LOCATION (t, cur_try_context->finally_locus);
2765   append_to_statement_list (t, &TREE_OPERAND (try_fin, 1));
2766
2767   append_to_statement_list (cur_try_context->finally_body,
2768                             &TREE_OPERAND (try_fin, 1));
2769
2770   t = tree_cons (NULL, rethrow_decl, NULL);
2771   t = build_function_call (input_location,
2772                            objc_exception_throw_decl, t);
2773   t = build_stmt (input_location, COND_EXPR,
2774                   c_common_truthvalue_conversion (input_location,
2775                                                   rethrow_decl),
2776                   t, NULL);
2777   SET_EXPR_LOCATION (t, cur_try_context->end_finally_locus);
2778   append_to_statement_list (t, &TREE_OPERAND (try_fin, 1));
2779
2780   return bind;
2781 }
2782
2783 /* We do not expect this to be used at the moment.
2784    If (a) it is possible to implement unwinder exceptions.
2785       (b) we do it... then it might be possibly useful.
2786 */
2787 static GTY(()) tree objc_eh_personality_decl;
2788
2789 static tree
2790 objc_eh_runtime_type (tree type)
2791 {
2792   tree ident, eh_id, decl, str;
2793
2794   gcc_unreachable ();
2795   if (type == error_mark_node)
2796     {
2797       /* Use 'ErrorMarkNode' as class name when error_mark_node is found
2798          to prevent an ICE.  Note that we know that the compiler will
2799          terminate with an error and this 'ErrorMarkNode' class name will
2800          never be actually used.  */
2801       ident = get_identifier ("ErrorMarkNode");
2802       goto make_err_class;
2803     }
2804
2805   if (POINTER_TYPE_P (type) && objc_is_object_id (TREE_TYPE (type)))
2806     {
2807       ident = get_identifier ("id");
2808       goto make_err_class;
2809     }
2810
2811   if (!POINTER_TYPE_P (type) || !TYPED_OBJECT (TREE_TYPE (type)))
2812     {
2813 #ifdef OBJCPLUS
2814       /* This routine is also called for c++'s catch clause; in which case,
2815          we use c++'s typeinfo decl. */
2816       return build_eh_type_type (type);
2817 #else
2818       error ("non-objective-c type '%T' cannot be caught", type);
2819       ident = get_identifier ("ErrorMarkNode");
2820       goto make_err_class;
2821 #endif
2822     }
2823   else
2824     ident = OBJC_TYPE_NAME (TREE_TYPE (type));
2825
2826 make_err_class:
2827   /* If this class was already referenced, then it will be output during
2828      meta-data emission, so we don't need to do it here.  */
2829   decl = get_objc_string_decl (ident, class_names);
2830   eh_id = add_objc_string (ident, class_names);
2831   if (!decl)
2832     {
2833       /* Not found ... so we need to build it - from the freshly-entered id.  */
2834       decl = get_objc_string_decl (ident, class_names);
2835       str = my_build_string (IDENTIFIER_LENGTH (ident) + 1,
2836                              IDENTIFIER_POINTER (ident));
2837       /* We have to finalize this var here, because this might be called after
2838          all the other metadata strings have been emitted.  */
2839       finish_var_decl (decl, str);
2840     }
2841   return eh_id;
2842 }
2843
2844 /* For NeXT ABI 0 and 1, the personality routines are just those of the 
2845    underlying language.  */
2846
2847 static tree
2848 objc_eh_personality (void)
2849 {
2850   if (!objc_eh_personality_decl)
2851 #ifndef OBJCPLUS
2852     objc_eh_personality_decl = build_personality_function ("gcc");
2853 #else
2854     objc_eh_personality_decl = build_personality_function ("gxx");
2855 #endif
2856   return objc_eh_personality_decl;
2857 }
2858
2859 /* --- interfaces --- */
2860
2861 static tree
2862 build_throw_stmt (location_t loc, tree throw_expr, bool rethrown ATTRIBUTE_UNUSED)
2863 {
2864   tree t;
2865   VEC(tree, gc) *parms = VEC_alloc (tree, gc, 1);
2866   /* A throw is just a call to the runtime throw function with the
2867      object as a parameter.  */
2868   VEC_quick_push (tree, parms, throw_expr);
2869   t = build_function_call_vec (loc, objc_exception_throw_decl, parms, NULL);
2870   VEC_free (tree, gc, parms);
2871   return add_stmt (t);
2872 }
2873
2874 /* Build __builtin_eh_pointer, or the moral equivalent.  In the case
2875    of Darwin, we'll arrange for it to be initialized (and associated
2876    with a binding) later.  */
2877
2878 static tree
2879 objc_build_exc_ptr (struct objc_try_context **cur_try_context)
2880 {
2881   if (flag_objc_sjlj_exceptions)
2882     {
2883       tree var = (*cur_try_context)->caught_decl;
2884       if (!var)
2885         {
2886           var = objc_create_temporary_var (objc_object_type, NULL);
2887           (*cur_try_context)->caught_decl = var;
2888         }
2889       return var;
2890     }
2891   else
2892     {
2893       tree t;
2894       t = builtin_decl_explicit (BUILT_IN_EH_POINTER);
2895       t = build_call_expr (t, 1, integer_zero_node);
2896       return fold_convert (objc_object_type, t);
2897     }
2898 }
2899
2900 static tree
2901 begin_catch (struct objc_try_context **cur_try_context, tree type,
2902              tree decl, tree compound, bool ellipsis ATTRIBUTE_UNUSED)
2903 {
2904   tree t;
2905   /* Record the data for the catch in the try context so that we can
2906      finalize it later.  We treat ellipsis the same way as catching
2907      with 'id xyz'.  */
2908   t = build_stmt (input_location, CATCH_EXPR, type, compound);
2909   (*cur_try_context)->current_catch = t;
2910
2911   /* Initialize the decl from the EXC_PTR_EXPR we get from the runtime.  */
2912   t = objc_build_exc_ptr (cur_try_context);
2913   t = convert (TREE_TYPE (decl), t);
2914   return build2 (MODIFY_EXPR, void_type_node, decl, t);
2915 }
2916
2917 static void
2918 finish_catch (struct objc_try_context **cur_try_context, tree current_catch)
2919 {
2920   append_to_statement_list (current_catch, &((*cur_try_context)->catch_list));
2921 }
2922
2923 static tree
2924 finish_try_stmt (struct objc_try_context **cur_try_context)
2925 {
2926   tree stmt;
2927   struct objc_try_context *c = *cur_try_context;
2928   /* If we're doing Darwin setjmp exceptions, build the big nasty.  */
2929   if (flag_objc_sjlj_exceptions)
2930     {
2931       bool save = in_late_binary_op;
2932       in_late_binary_op = true;
2933       if (!c->finally_body)
2934         {
2935           c->finally_locus = input_location;
2936           c->end_finally_locus = input_location;
2937         }
2938       stmt = next_sjlj_build_try_catch_finally (cur_try_context);
2939       in_late_binary_op = save;
2940     }
2941   else
2942     /* This doesn't happen at the moment... but maybe one day... */
2943     {
2944       /* Otherwise, nest the CATCH inside a FINALLY.  */
2945       stmt = c->try_body;
2946       if (c->catch_list)
2947         stmt = build_stmt (c->try_locus, TRY_CATCH_EXPR, stmt, c->catch_list);
2948       if (c->finally_body)
2949         stmt = build_stmt (c->try_locus, TRY_FINALLY_EXPR, stmt, c->finally_body);
2950     }
2951   return stmt;
2952 }
2953
2954 #include "gt-objc-objc-next-runtime-abi-01.h"