OSDN Git Service

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