OSDN Git Service

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