OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [gcc/] [objc/] [objc-next-runtime-abi-02.c] - Blame information for rev 764

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 717 jeremybenn
/* Next Runtime (ABI-2) private.
2
   Copyright (C) 2011 Free Software Foundation, Inc.
3
 
4
   Contributed by Iain Sandoe and based, in part, on an implementation in
5
   'branches/apple/trunk' contributed by Apple Computer Inc.
6
 
7
This file is part of GCC.
8
 
9
GCC is free software; you can redistribute it and/or modify
10
it under the terms of the GNU General Public License as published by
11
the Free Software Foundation; either version 3, or (at your option)
12
any later version.
13
 
14
GCC is distributed in the hope that it will be useful,
15
but WITHOUT ANY WARRANTY; without even the implied warranty of
16
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17
GNU General Public License for more details.
18
 
19
You should have received a copy of the GNU General Public License
20
along with GCC; see the file COPYING3.  If not see
21
<http://www.gnu.org/licenses/>.  */
22
 
23
/* The NeXT ABI2 is used for m64 implementations on Darwin/OSX machines.
24
 
25
   This version is intended to match (logically) the output of Apple's
26
   4.2.1 compiler.  */
27
 
28
#include "config.h"
29
#include "system.h"
30
#include "coretypes.h"
31
#include "tm.h"
32
#include "tree.h"
33
 
34
#ifdef OBJCPLUS
35
#include "cp-tree.h"
36
#else
37
#include "c-tree.h"
38
#include "c-lang.h"
39
#endif
40
#include "langhooks.h"
41
#include "c-family/c-objc.h"
42
#include "objc-act.h"
43
 
44
/* When building Objective-C++, we are not linking against the C front-end
45
   and so need to replicate the C tree-construction functions in some way.  */
46
#ifdef OBJCPLUS
47
#define OBJCP_REMAP_FUNCTIONS
48
#include "objcp-decl.h"
49
#endif  /* OBJCPLUS */
50
 
51
#include "ggc.h"
52
#include "target.h"
53
#include "tree-iterator.h"
54
 
55
#include "objc-runtime-hooks.h"
56
#include "objc-runtime-shared-support.h"
57
#include "objc-encoding.h"
58
 
59
/* ABI 2 Private definitions. */
60
#define DEF_CONSTANT_STRING_CLASS_NAME "NSConstantString"
61
 
62
#define TAG_GETCLASS            "objc_getClass"
63
#define TAG_GETMETACLASS        "objc_getMetaClass"
64
 
65
#define TAG_MSGSEND             "objc_msgSend"
66
#define TAG_MSGSENDSUPER        "objc_msgSendSuper"
67
#define TAG_MSGSEND_STRET       "objc_msgSend_stret"
68
#define TAG_MSGSENDSUPER_STRET  "objc_msgSendSuper_stret"
69
 
70
#define TAG_NEXT_EHVTABLE_NAME  "objc_ehtype_vtable"
71
#define TAG_V2_EH_TYPE          "objc_ehtype_t"
72
 
73
#define UTAG_V2_CLASS           "_class_t"
74
#define UTAG_V2_CLASS_RO        "_class_ro_t"
75
#define UTAG_V2_PROTOCOL        "_protocol_t"
76
#define UTAG_V2_PROTOCOL_LIST   "_protocol_list_t"
77
 
78
#define UTAG_V2_EH_TYPE         "_objc_ehtype_t"
79
 
80
#define OBJC2_CLS_HAS_CXX_STRUCTORS     0x0004L
81
 
82
enum objc_v2_tree_index
83
{
84
  /* Templates.  */
85
  OCTI_V2_CLS_TEMPL,
86
  OCTI_V2_CAT_TEMPL,
87
  OCTI_V2_CLS_RO_TEMPL,
88
  OCTI_V2_PROTO_TEMPL,
89
  OCTI_V2_IVAR_TEMPL,
90
  OCTI_V2_IVAR_LIST_TEMPL,
91
  OCTI_V2_MESSAGE_REF_TEMPL,
92
  OCTI_V2_SUPER_MESSAGE_REF_TEMPL,
93
 
94
  OCTI_V2_MESSAGE_SELECTOR_TYPE,
95
  OCTI_V2_SUPER_MESSAGE_SELECTOR_TYPE,
96
  OCTI_V2_IMP_TYPE,
97
  OCTI_V2_SUPER_IMP_TYPE,
98
 
99
  OCTI_V2_CACHE_DECL,
100
  OCTI_V2_VTABLE_DECL,
101
 
102
  OCTI_V2_PROPERTY_TEMPL,
103
 
104
  /* V2 messaging.  */
105
  OCTI_V2_UMSG_FIXUP_DECL,
106
  OCTI_V2_UMSG_STRET_FIXUP_DECL,
107
  OCTI_V2_UMSG_ID_FIXUP_DECL,
108
  OCTI_V2_UMSG_ID_STRET_FIXUP_DECL,
109
  OCTI_V2_UMSG_SUPER2_FIXUP_DECL,
110
  OCTI_V2_UMSG_SUPER2_STRET_FIXUP_DECL,
111
 
112
  /* Exceptions - related.  */
113
  OCTI_V2_BEGIN_CATCH_DECL,
114
  OCTI_V2_END_CATCH_DECL,
115
  OCTI_V2_RETHROW_DECL,
116
 
117
  OCTI_V2_MAX
118
};
119
 
120
#define objc_v2_class_template  objc_v2_global_trees[OCTI_V2_CLS_TEMPL]
121
#define objc_v2_class_ro_template \
122
                                objc_v2_global_trees[OCTI_V2_CLS_RO_TEMPL]
123
#define objc_v2_category_template \
124
                                objc_v2_global_trees[OCTI_V2_CAT_TEMPL]
125
#define objc_v2_protocol_template \
126
                                objc_v2_global_trees[OCTI_V2_PROTO_TEMPL]
127
 
128
/* struct message_ref_t */
129
#define objc_v2_message_ref_template \
130
                                objc_v2_global_trees[OCTI_V2_MESSAGE_REF_TEMPL]
131
 
132
#define objc_v2_ivar_list_ptr   objc_v2_global_trees[OCTI_V2_IVAR_LIST_TEMPL]
133
 
134
/* struct super_message_ref_t */
135
#define objc_v2_super_message_ref_template \
136
                                objc_v2_global_trees[OCTI_V2_SUPER_MESSAGE_REF_TEMPL]
137
 
138
/* struct message_ref_t* */
139
#define objc_v2_selector_type   objc_v2_global_trees[OCTI_V2_MESSAGE_SELECTOR_TYPE]
140
/* struct super_super_message_ref_t */
141
#define objc_v2_super_selector_type \
142
                                objc_v2_global_trees[OCTI_V2_SUPER_MESSAGE_SELECTOR_TYPE]
143
#define objc_v2_imp_type        objc_v2_global_trees[OCTI_V2_IMP_TYPE]
144
#define objc_v2_super_imp_type  objc_v2_global_trees[OCTI_V2_SUPER_IMP_TYPE]
145
 
146
#define UOBJC_V2_CACHE_decl     objc_v2_global_trees[OCTI_V2_CACHE_DECL]
147
#define UOBJC_V2_VTABLE_decl    objc_v2_global_trees[OCTI_V2_VTABLE_DECL]
148
 
149
#define objc_v2_ivar_template   objc_v2_global_trees[OCTI_V2_IVAR_TEMPL]
150
#define objc_v2_property_template \
151
                                objc_v2_global_trees[OCTI_V2_PROPERTY_TEMPL]
152
 
153
/* V2 Messaging */
154
 
155
/* objc_msgSend_fixup_rtp */
156
#define umsg_fixup_decl         objc_v2_global_trees[OCTI_V2_UMSG_FIXUP_DECL]
157
/* objc_msgSend_stret_fixup_rtp */
158
#define umsg_stret_fixup_decl   objc_v2_global_trees[OCTI_V2_UMSG_STRET_FIXUP_DECL]
159
/* objc_msgSendId_fixup_rtp */
160
#define umsg_id_fixup_decl      objc_v2_global_trees[OCTI_V2_UMSG_ID_FIXUP_DECL]
161
/* objc_msgSendId_stret_fixup_rtp */
162
#define umsg_id_stret_fixup_decl \
163
                                objc_v2_global_trees[OCTI_V2_UMSG_ID_STRET_FIXUP_DECL]
164
/* objc_msgSendSuper2_fixup_rtp */
165
#define umsg_id_super2_fixup_decl \
166
                                objc_v2_global_trees[OCTI_V2_UMSG_SUPER2_FIXUP_DECL]
167
/* objc_msgSendSuper2_stret_fixup_rtp */
168
#define umsg_id_super2_stret_fixup_decl \
169
                                objc_v2_global_trees[OCTI_V2_UMSG_SUPER2_STRET_FIXUP_DECL]
170
 
171
#define objc2_begin_catch_decl  objc_v2_global_trees[OCTI_V2_BEGIN_CATCH_DECL]
172
#define objc2_end_catch_decl    objc_v2_global_trees[OCTI_V2_END_CATCH_DECL]
173
#define objc_rethrow_exception_decl \
174
                                objc_v2_global_trees[OCTI_V2_RETHROW_DECL]
175
 
176
/* rt_trees identifiers - shared between NeXT implementations.  These allow
177
   the FE to tag meta-data in a manner that survives LTO and can be used when
178
   the  runtime requires that certain meta-data items appear in particular
179
   named sections.  */
180
 
181
#include "objc-next-metadata-tags.h"
182
extern GTY(()) tree objc_rt_trees[OCTI_RT_META_MAX];
183
 
184
/* The OCTI_V2_... enumeration itself is in above.  */
185
static GTY(()) tree objc_v2_global_trees[OCTI_V2_MAX];
186
 
187
static void next_runtime_02_initialize (void);
188
 
189
static void build_v2_message_ref_templates (void);
190
static void build_v2_class_templates (void);
191
static void build_v2_super_template (void);
192
static void build_v2_category_template (void);
193
static void build_v2_protocol_template (void);
194
 
195
static tree next_runtime_abi_02_super_superclassfield_id (void);
196
 
197
static tree next_runtime_abi_02_class_decl (tree);
198
static tree next_runtime_abi_02_metaclass_decl (tree);
199
static tree next_runtime_abi_02_category_decl (tree);
200
static tree next_runtime_abi_02_protocol_decl (tree);
201
static tree next_runtime_abi_02_string_decl (tree, const char *, string_section);
202
 
203
static tree next_runtime_abi_02_get_class_reference (tree);
204
static tree next_runtime_abi_02_build_selector_reference (location_t, tree, tree);
205
static tree next_runtime_abi_02_get_protocol_reference (location_t, tree);
206
static tree next_runtime_abi_02_build_ivar_ref (location_t, tree, tree);
207
static tree next_runtime_abi_02_get_class_super_ref (location_t, struct imp_entry *, bool);
208
static tree next_runtime_abi_02_get_category_super_ref (location_t, struct imp_entry *, bool);
209
 
210
static tree next_runtime_abi_02_receiver_is_class_object (tree);
211
static void next_runtime_abi_02_get_arg_type_list_base (VEC(tree,gc) **, tree,
212
                                                        int, int);
213
static tree next_runtime_abi_02_build_objc_method_call (location_t, tree, tree,
214
                                                        tree, tree, tree, int);
215
static bool next_runtime_abi_02_setup_const_string_class_decl (void);
216
static tree next_runtime_abi_02_build_const_string_constructor (location_t, tree, int);
217
 
218
static tree create_extern_decl (tree, const char *);
219
 
220
static void objc_generate_v2_next_metadata (void);
221
static bool objc2_objc_exception_attr (tree);
222
 
223
/* void build_v2_protocol_reference (tree);*/
224
static void build_v2_ehtype_template (void);
225
static void build_v2_eh_catch_objects (void);
226
static tree next_runtime_02_eh_type (tree);
227
static tree objc_eh_personality (void);
228
static tree build_throw_stmt (location_t, tree, bool);
229
static tree objc_build_exc_ptr (struct objc_try_context **);
230
static tree begin_catch (struct objc_try_context **, tree, tree, tree, bool);
231
static void finish_catch (struct objc_try_context **, tree);
232
static tree finish_try_stmt (struct objc_try_context **);
233
 
234
/* TODO: Use an objc-map.  */
235
static GTY ((length ("SIZEHASHTABLE"))) hash *extern_names;
236
 
237
bool
238
objc_next_runtime_abi_02_init (objc_runtime_hooks *rthooks)
239
{
240
  extern_names = ggc_alloc_cleared_vec_hash (SIZEHASHTABLE);
241
 
242
  if (flag_objc_exceptions && flag_objc_sjlj_exceptions)
243
    {
244
      inform (UNKNOWN_LOCATION, "%<-fobjc-sjlj-exceptions%> is ignored for "
245
                                "%<-fnext-runtime%> when %<-fobjc-abi-version%> >= 2");
246
      flag_objc_sjlj_exceptions = 0;
247
    }
248
 
249
  rthooks->initialize = next_runtime_02_initialize;
250
  rthooks->default_constant_string_class_name = DEF_CONSTANT_STRING_CLASS_NAME;
251
  rthooks->tag_getclass = TAG_GETCLASS;
252
  rthooks->super_superclassfield_ident = next_runtime_abi_02_super_superclassfield_id;
253
 
254
  rthooks->class_decl = next_runtime_abi_02_class_decl;
255
  rthooks->metaclass_decl = next_runtime_abi_02_metaclass_decl;
256
  rthooks->category_decl = next_runtime_abi_02_category_decl;
257
  rthooks->protocol_decl = next_runtime_abi_02_protocol_decl;
258
  rthooks->string_decl = next_runtime_abi_02_string_decl;
259
 
260
  rthooks->get_class_reference = next_runtime_abi_02_get_class_reference;
261
  rthooks->build_selector_reference = next_runtime_abi_02_build_selector_reference;
262
  rthooks->get_protocol_reference = next_runtime_abi_02_get_protocol_reference;
263
  rthooks->build_ivar_reference = next_runtime_abi_02_build_ivar_ref;
264
  rthooks->get_class_super_ref = next_runtime_abi_02_get_class_super_ref;
265
  rthooks->get_category_super_ref = next_runtime_abi_02_get_category_super_ref;
266
 
267
  rthooks->receiver_is_class_object = next_runtime_abi_02_receiver_is_class_object;
268
  rthooks->get_arg_type_list_base = next_runtime_abi_02_get_arg_type_list_base;
269
  rthooks->build_objc_method_call = next_runtime_abi_02_build_objc_method_call;
270
 
271
  rthooks->setup_const_string_class_decl =
272
                                next_runtime_abi_02_setup_const_string_class_decl;
273
  rthooks->build_const_string_constructor =
274
                                next_runtime_abi_02_build_const_string_constructor;
275
 
276
  rthooks->build_throw_stmt = build_throw_stmt;
277
  rthooks->build_exc_ptr = objc_build_exc_ptr;
278
  rthooks->begin_catch = begin_catch;
279
  rthooks->finish_catch = finish_catch;
280
  rthooks->finish_try_stmt = finish_try_stmt;
281
 
282
  rthooks->generate_metadata = objc_generate_v2_next_metadata;
283
  return true;
284
}
285
 
286
/* We need a way to convey what kind of meta-data are represented by a given
287
   variable, since each type is expected (by the runtime) to be found in a
288
   specific named section.  The solution must be usable with LTO.
289
 
290
   The scheme used for NeXT ABI 0/1 (partial matching of variable names) is not
291
   satisfactory when LTO is used with ABI-2.  We now tag ObjC meta-data with
292
   identification attributes in the front end.  The back-end may choose to act
293
   on these as it requires.  */
294
 
295
static void
296
next_runtime_abi_02_init_metadata_attributes (void)
297
{
298
  if (!objc_meta)
299
    objc_meta = get_identifier ("OBJC2META");
300
 
301
  if (!meta_base)
302
    meta_base = get_identifier ("V2_BASE");
303
 
304
  meta_class = get_identifier ("G2_CLAS");
305
  meta_metaclass = get_identifier ("G2_META");
306
  meta_category =
307
  meta_protocol = meta_base;
308
 
309
  meta_clac_vars =
310
  meta_clai_vars = meta_base;
311
 
312
  meta_clac_meth =
313
  meta_clai_meth =
314
  meta_catc_meth =
315
  meta_cati_meth =
316
  meta_proto_cls_meth =
317
  meta_proto_nst_meth = meta_base;
318
 
319
  meta_clas_prot =
320
  meta_catg_prot = meta_base;
321
 
322
  meta_sel_refs = get_identifier ("V2_SRFS");
323
 
324
  meta_class_name =
325
  meta_meth_name =
326
  meta_meth_type =
327
  meta_prop_name_attr = get_identifier ("V2_STRG");
328
 
329
  meta_mref = get_identifier ("V2_MREF");
330
  meta_class_ref = get_identifier ("V2_CLRF");
331
  meta_superclass_ref = get_identifier ("V2_SURF");
332
 
333
  meta_label_classlist = get_identifier ("V2_CLAB");
334
  meta_label_nonlazy_classlist = get_identifier ("V2_NLCL");
335
  meta_label_categorylist = get_identifier ("V2_CALA");
336
  meta_label_nonlazy_categorylist = get_identifier ("V2_NLCA");
337
 
338
  meta_label_protocollist = get_identifier ("V2_PLST");
339
  meta_proto_ref = get_identifier ("V2_PRFS");
340
 
341
  meta_info = get_identifier ("V2_INFO");
342
 
343
  meta_ehtype = get_identifier ("V2_EHTY");
344
 
345
  meta_const_str = get_identifier ("V2_CSTR");
346
}
347
 
348
static void next_runtime_02_initialize (void)
349
{
350
  tree type;
351
#ifdef OBJCPLUS
352
  /* For all NeXT objc ABIs -fobjc-call-cxx-cdtors is on by
353
     default.  */
354
  if (!global_options_set.x_flag_objc_call_cxx_cdtors)
355
    global_options.x_flag_objc_call_cxx_cdtors = 1;
356
#endif
357
 
358
  /* Set up attributes to be attached to the meta-data so that they
359
     will be placed in the correct sections.  */
360
  next_runtime_abi_02_init_metadata_attributes ();
361
 
362
  /* `struct objc_selector *' */
363
  objc_selector_type = build_pointer_type (xref_tag (RECORD_TYPE,
364
                                           get_identifier (TAG_SELECTOR)));
365
 
366
  /* IMP : id (*) (id, _message_ref_t*, ...)
367
     SUPER_IMP : id (*) ( super_t*, _super_message_ref_t*, ...)
368
     objc_v2_selector_type.  */
369
  build_v2_message_ref_templates ();
370
 
371
  objc_v2_ivar_list_ptr =
372
                build_pointer_type (xref_tag (RECORD_TYPE,
373
                                    get_identifier ("_ivar_list_t")));
374
 
375
  objc_prop_list_ptr =
376
                build_pointer_type (xref_tag (RECORD_TYPE,
377
                                    get_identifier ("_prop_list_t")));
378
 
379
  build_v2_class_templates ();
380
  build_v2_super_template ();
381
  build_v2_protocol_template ();
382
  build_v2_category_template ();
383
 
384
  /* id objc_msgSend_fixup_rtp (id, struct message_ref_t*, ...); */
385
  type = build_varargs_function_type_list (objc_object_type,
386
                                                   objc_object_type,
387
                                                   objc_v2_selector_type,
388
                                                   NULL_TREE);
389
  umsg_fixup_decl =  add_builtin_function ("objc_msgSend_fixup",
390
                                           type, 0, NOT_BUILT_IN,
391
                                           NULL, NULL_TREE);
392
  TREE_NOTHROW (umsg_fixup_decl) = 0;
393
 
394
  /* id objc_msgSend_stret_fixup_rtp (id, struct message_ref_t*, ...); */
395
  umsg_stret_fixup_decl = add_builtin_function ("objc_msgSend_stret_fixup",
396
                                                type, 0, NOT_BUILT_IN,
397
                                                NULL, NULL_TREE);
398
  TREE_NOTHROW (umsg_stret_fixup_decl) = 0;
399
 
400
  /* id objc_msgSendId_fixup_rtp (id, struct message_ref_t*, ...); */
401
  umsg_id_fixup_decl = add_builtin_function ("objc_msgSendId_fixup",
402
                                             type, 0, NOT_BUILT_IN,
403
                                             NULL, NULL_TREE);
404
  TREE_NOTHROW (umsg_id_fixup_decl) = 0;
405
 
406
  /* id objc_msgSendId_stret_fixup_rtp
407
                        (id, struct message_ref_t*, ...); */
408
  umsg_id_stret_fixup_decl = add_builtin_function ("objc_msgSendId_stret_fixup",
409
                                                   type, 0, NOT_BUILT_IN,
410
                                                   NULL, NULL_TREE);
411
  TREE_NOTHROW (umsg_id_stret_fixup_decl) = 0;
412
 
413
 /* id objc_msgSendSuper2_fixup_rtp
414
                        (struct objc_super *, struct message_ref_t*, ...); */
415
  type = build_varargs_function_type_list (objc_object_type,
416
                                           objc_super_type,
417
                                           objc_v2_super_selector_type,
418
                                           NULL_TREE);
419
  umsg_id_super2_fixup_decl = add_builtin_function ("objc_msgSendSuper2_fixup",
420
                                                    type, 0, NOT_BUILT_IN,
421
                                                    NULL, NULL_TREE);
422
  TREE_NOTHROW (umsg_id_super2_fixup_decl) = 0;
423
 
424
  /* id objc_msgSendSuper2_stret_fixup_rtp
425
                        (struct objc_super *, struct message_ref_t*, ...); */
426
  umsg_id_super2_stret_fixup_decl =
427
                        add_builtin_function ("objc_msgSendSuper2_stret_fixup",
428
                                              type, 0, NOT_BUILT_IN,
429
                                              NULL, NULL_TREE);
430
  TREE_NOTHROW (umsg_id_super2_stret_fixup_decl) = 0;
431
 
432
  /* Present in the library, but unused by the FE.  */
433
  /* Protocol *objc_getProtocol (const char *)
434
  type = build_function_type_list (objc_protocol_type,
435
                                   const_string_type_node,
436
                                   NULL_TREE);
437
  objc_v2_getprotocol_decl = add_builtin_function ("objc_getProtocol",
438
                                                    type, 0, NOT_BUILT_IN,
439
                                                    NULL, NULL_TREE);
440
  TREE_NOTHROW (objc_v2_getprotocol_decl) = 0;*/
441
 
442
  UOBJC_V2_CACHE_decl = create_extern_decl (ptr_type_node,
443
                                            "_objc_empty_cache");
444
 
445
  UOBJC_V2_VTABLE_decl = create_extern_decl (objc_v2_imp_type,
446
                                             "_objc_empty_vtable");
447
 
448
  /* id objc_getClass (const char *); */
449
  type = build_function_type_list (objc_object_type,
450
                                   const_string_type_node,
451
                                   NULL_TREE);
452
  objc_get_class_decl = add_builtin_function (TAG_GETCLASS,
453
                                              type, 0, NOT_BUILT_IN,
454
                                              NULL, NULL_TREE);
455
 
456
  /* id objc_getMetaClass (const char *); */
457
  objc_get_meta_class_decl = add_builtin_function (TAG_GETMETACLASS,
458
                                                   type, 0, NOT_BUILT_IN,
459
                                                   NULL, NULL_TREE);
460
 
461
  /* This is the type of all of the following functions
462
     objc_copyStruct().  */
463
  type = build_function_type_list (void_type_node,
464
                                   ptr_type_node,
465
                                   const_ptr_type_node,
466
                                   ptrdiff_type_node,
467
                                   boolean_type_node,
468
                                   boolean_type_node,
469
                                   NULL_TREE);
470
  /* Declare the following function:
471
         void
472
         objc_copyStruct (void *destination, const void *source,
473
                          ptrdiff_t size, BOOL is_atomic, BOOL has_strong); */
474
  objc_copyStruct_decl = add_builtin_function ("objc_copyStruct",
475
                                                   type, 0, NOT_BUILT_IN,
476
                                                   NULL, NULL_TREE);
477
  TREE_NOTHROW (objc_copyStruct_decl) = 0;
478
  objc_getPropertyStruct_decl = NULL_TREE;
479
  objc_setPropertyStruct_decl = NULL_TREE;
480
 
481
  gcc_assert (!flag_objc_sjlj_exceptions);
482
 
483
  /* Although we warn that fobjc-exceptions is required for exceptions
484
     code, we carry on and create it anyway.  */
485
 
486
  /* This can be required, even when exceptions code is not present,
487
     when an __attribute__((objc_exception)) is applied to a
488
     class.  */
489
  build_v2_ehtype_template ();
490
 
491
  /* void * objc_begin_catch (void *) */
492
  type = build_function_type_list (ptr_type_node,
493
                                   ptr_type_node, NULL_TREE);
494
 
495
  objc2_begin_catch_decl = add_builtin_function ("objc_begin_catch",
496
                                                 type, 0, NOT_BUILT_IN,
497
                                                 NULL, NULL_TREE);
498
  TREE_NOTHROW (objc2_begin_catch_decl) = 0;
499
 
500
  /* void objc_end_catch () */
501
  type = build_function_type_list (void_type_node, NULL_TREE);
502
  objc2_end_catch_decl = add_builtin_function ("objc_end_catch",
503
                                                type, 0, NOT_BUILT_IN,
504
                                                NULL, NULL_TREE);
505
  TREE_NOTHROW (objc2_end_catch_decl) = 0;
506
 
507
  /* void objc_exception_rethrow (void) */
508
  objc_rethrow_exception_decl =
509
                        add_builtin_function ("objc_exception_rethrow",
510
                                              type, 0, NOT_BUILT_IN,
511
                                              NULL, NULL_TREE);
512
  TREE_NOTHROW (objc_rethrow_exception_decl) = 0;
513
  using_eh_for_cleanups ();
514
  lang_hooks.eh_runtime_type = next_runtime_02_eh_type;
515
  lang_hooks.eh_personality = objc_eh_personality;
516
}
517
 
518
/* NOTE --- templates --- */
519
 
520
/* Set 'objc_v2_message_ref_template' to the data type node for
521
   'struct _message_ref_t'.  This needs to be done just once per
522
   compilation.  Also Set 'objc_v2_super_message_ref_template' to data
523
   type node for 'struct _super_message_ref_t'.  */
524
 
525
/* struct _message_ref_t
526
   {
527
     IMP messenger;
528
     SEL name;
529
   };
530
   where IMP is: id (*) (id, _message_ref_t*, ...)
531
*/
532
 
533
/* struct _super_message_ref_t
534
   {
535
     SUPER_IMP messenger;
536
     SEL name;
537
   };
538
   where SUPER_IMP is: id (*) ( super_t*, _super_message_ref_t*, ...)
539
*/
540
 
541
static void
542
build_v2_message_ref_templates (void)
543
{
544
  tree ptr_message_ref_t;
545
  tree decls, *chain = NULL;
546
 
547
  /* struct _message_ref_t {...} */
548
  objc_v2_message_ref_template =
549
                objc_start_struct (get_identifier ("_message_ref_t"));
550
 
551
  /* IMP messenger; */
552
  ptr_message_ref_t =
553
                build_pointer_type (xref_tag (RECORD_TYPE,
554
                                    get_identifier ("_message_ref_t")));
555
 
556
  objc_v2_imp_type =
557
                build_pointer_type (build_function_type_list
558
                                        (objc_object_type,
559
                                         objc_object_type,
560
                                         ptr_message_ref_t,
561
                                         NULL_TREE));
562
 
563
  decls = add_field_decl (objc_v2_imp_type, "messenger", &chain);
564
 
565
  /* SEL name; */
566
  add_field_decl (objc_selector_type, "name", &chain);
567
 
568
  objc_finish_struct (objc_v2_message_ref_template, decls);
569
 
570
  objc_v2_selector_type = build_pointer_type (objc_v2_message_ref_template);
571
 
572
  chain = NULL;
573
  /* struct _super_message_ref_t {...} */
574
  objc_v2_super_message_ref_template =
575
                objc_start_struct (get_identifier ("_super_message_ref_t"));
576
 
577
  /* SUPER_IMP messenger; */
578
  ptr_message_ref_t = build_pointer_type
579
                        (xref_tag (RECORD_TYPE,
580
                                   get_identifier ("_super_message_ref_t")));
581
 
582
  objc_v2_super_imp_type =
583
                build_pointer_type (build_function_type_list
584
                                        (objc_object_type,
585
                                         objc_super_type,
586
                                         ptr_message_ref_t,
587
                                         NULL_TREE));
588
 
589
  add_field_decl (objc_v2_super_imp_type, "messenger", &chain);
590
 
591
  /* SEL name; */
592
  add_field_decl (objc_selector_type, "name", &chain);
593
 
594
  objc_finish_struct (objc_v2_super_message_ref_template, decls);
595
  objc_v2_super_selector_type =
596
                build_pointer_type (objc_v2_super_message_ref_template);
597
}
598
 
599
/* Build following types which represent each class implementation.
600
 
601
struct class_ro_t
602
{
603
    uint32_t const flags;
604
    uint32_t const instanceStart;
605
    uint32_t const instanceSize;
606
#ifdef __LP64__
607
    uint32_t const reserved;
608
#endif
609
    const uint8_t * const ivarLayout;
610
    const char *const name;
611
    const struct method_list_t * const baseMethods;
612
    const struct objc_protocol_list *const baseProtocols;
613
    const struct ivar_list_t *const ivars;
614
    const uint8_t * const weakIvarLayout;
615
    const struct _prop_list_t * const properties;
616
};
617
 
618
struct class_t
619
{
620
    struct class_t *isa;
621
    struct class_t *superclass;
622
    void *cache;
623
    IMP *vtable;
624
 
625
    ...When this is active - it will point to a rw version, but
626
       when we build the meta-data we point it to the ro...
627
    struct class_ro_t *data;
628
};
629
 
630
*/
631
 
632
static void
633
build_v2_class_templates (void)
634
{
635
  tree cnst_strg_type;
636
  tree decls, *chain = NULL;
637
 
638
  /* struct class_ro_t {...} */
639
  objc_v2_class_ro_template =
640
        objc_start_struct (get_identifier (UTAG_V2_CLASS_RO));
641
 
642
  /* uint32_t const flags; */
643
  decls = add_field_decl (integer_type_node, "flags", &chain);
644
 
645
  /* uint32_t const instanceStart; */
646
  add_field_decl (integer_type_node, "instanceStart", &chain);
647
 
648
  /* uint32_t const instanceSize; */
649
  add_field_decl (integer_type_node, "instanceSize", &chain);
650
 
651
  /* This ABI is currently only used on m64 NeXT.  We always
652
     explicitly declare the alignment padding.  */
653
  /* uint32_t const reserved; */
654
  add_field_decl (integer_type_node, "reserved", &chain);
655
 
656
  /* const uint8_t * const ivarLayout; */
657
  cnst_strg_type = build_pointer_type (unsigned_char_type_node);
658
  add_field_decl (cnst_strg_type, "ivarLayout", &chain);
659
 
660
  /* const char *const name; */
661
  add_field_decl (string_type_node, "name", &chain);
662
 
663
  /* const struct method_list_t * const baseMethods; */
664
  add_field_decl (objc_method_list_ptr, "baseMethods", &chain);
665
 
666
  /* const struct objc_protocol_list *const baseProtocols; */
667
  add_field_decl (build_pointer_type
668
                        (xref_tag (RECORD_TYPE,
669
                                   get_identifier (UTAG_V2_PROTOCOL_LIST))),
670
                                  "baseProtocols", &chain);
671
 
672
  /* const struct ivar_list_t *const ivars; */
673
  add_field_decl (objc_v2_ivar_list_ptr, "ivars", &chain);
674
 
675
  /* const uint8_t * const weakIvarLayout; */
676
  add_field_decl (cnst_strg_type, "weakIvarLayout",  &chain);
677
 
678
  /* struct _prop_list_t * baseProperties; */
679
  add_field_decl (objc_prop_list_ptr, "baseProperties", &chain);
680
 
681
  objc_finish_struct (objc_v2_class_ro_template, decls);
682
 
683
  chain = NULL;
684
  /* struct class_t {...} */
685
  objc_v2_class_template =
686
        objc_start_struct (get_identifier (UTAG_V2_CLASS));
687
 
688
  /* struct class_t *isa; */
689
  decls = add_field_decl (build_pointer_type (objc_v2_class_template),
690
                          "isa", &chain);
691
 
692
  /* struct class_t * const superclass; */
693
  add_field_decl (build_pointer_type (objc_v2_class_template),
694
                                      "superclass", &chain);
695
 
696
  /* void *cache; */
697
  add_field_decl (build_pointer_type (void_type_node), "cache", &chain);
698
 
699
  /* IMP *vtable; */
700
  add_field_decl (build_pointer_type (objc_v2_imp_type), "vtable", &chain);
701
 
702
  /* struct class_ro_t *ro; */
703
  add_field_decl (build_pointer_type (objc_v2_class_ro_template), "ro", &chain);
704
 
705
  objc_finish_struct (objc_v2_class_template, decls);
706
}
707
 
708
/* struct _objc_super
709
   {
710
     struct _objc_object *self;
711
     Class cls;
712
   }; */
713
void
714
build_v2_super_template (void)
715
{
716
  tree decls, *chain = NULL;
717
 
718
  objc_super_template = objc_start_struct (get_identifier (UTAG_SUPER));
719
 
720
  /* struct _objc_object *self; */
721
  decls = add_field_decl (objc_object_type, "self", &chain);
722
 
723
  /* Class cls; */
724
  add_field_decl (objc_class_type, "cls", &chain);
725
 
726
  objc_finish_struct (objc_super_template, decls);
727
}
728
 
729
/* struct protocol_t
730
  {
731
     Class isa;
732
     const char * const protocol_name;
733
     const struct protocol_list_t * const protocol_list;
734
     const struct method_list_t * const instance_methods;
735
     const struct method_list_t * const class_methods;
736
     const struct method_list_t * optionalInstanceMethods;
737
     const struct method_list_t * optionalClassMethod
738
     const struct _prop_list_t * const properties;
739
     const uint32_t size;
740
     const uint32_t flags;
741
   }
742
*/
743
static void
744
build_v2_protocol_template (void)
745
{
746
  tree decls, *chain = NULL;
747
 
748
  objc_v2_protocol_template =
749
        objc_start_struct (get_identifier (UTAG_V2_PROTOCOL));
750
 
751
  /* Class isa; */
752
  decls = add_field_decl (objc_object_type, "isa", &chain);
753
 
754
  /* char *protocol_name; */
755
  add_field_decl (string_type_node, "protocol_name", &chain);
756
 
757
  /* const struct protocol_list_t * const protocol_list; */
758
  add_field_decl (build_pointer_type (objc_v2_protocol_template),
759
                  "protocol_list", &chain);
760
 
761
  /* const struct method_list_t * const instance_methods; */
762
  add_field_decl (objc_method_proto_list_ptr,  "instance_methods", &chain);
763
 
764
  /* const struct method_list_t * const class_methods; */
765
  add_field_decl (objc_method_proto_list_ptr, "class_methods", &chain);
766
 
767
  /* const struct method_list_t * optionalInstanceMethods; */
768
  add_field_decl (objc_method_proto_list_ptr, "optionalInstanceMethods", &chain);
769
 
770
  /* const struct method_list_t * optionalClassMethods; */
771
  add_field_decl (objc_method_proto_list_ptr, "optionalClassMethods", &chain);
772
 
773
  /* struct _prop_list_t * properties; */
774
  add_field_decl (objc_prop_list_ptr, "properties", &chain);
775
 
776
  /* const uint32_t size; */
777
  add_field_decl (integer_type_node, "size", &chain);
778
 
779
  /* const uint32_t flags; */
780
  add_field_decl (integer_type_node, "flags", &chain);
781
 
782
  objc_finish_struct (objc_v2_protocol_template, decls);
783
}
784
 
785
/* Build type for a category:
786
   struct category_t
787
   {
788
     const char * const name;
789
     struct class_t *const cls;
790
     const struct method_list_t * const instance_methods;
791
     const struct method_list_t * const class_methods;
792
     const struct protocol_list_t * const protocols;
793
     const struct _prop_list_t * const properties;
794
   }
795
*/
796
 
797
static void
798
build_v2_category_template (void)
799
{
800
  tree decls, *chain = NULL;
801
 
802
  objc_v2_category_template =
803
        objc_start_struct (get_identifier ("_category_t"));
804
 
805
  /* char *name; */
806
  decls = add_field_decl (string_type_node, "name", &chain);
807
 
808
  /* struct class_t *const cls; */
809
  add_field_decl (build_pointer_type (objc_v2_class_template), "cls", &chain);
810
 
811
  /* struct method_list_t *instance_methods; */
812
  add_field_decl (objc_method_list_ptr, "instance_methods", &chain);
813
 
814
  /* struct method_list_t *class_methods; */
815
  add_field_decl (objc_method_list_ptr, "class_methods", &chain);
816
 
817
  /* struct protocol_list_t *protocol_list; */
818
  add_field_decl (build_pointer_type (objc_v2_protocol_template),
819
                  "protocol_list", &chain );
820
 
821
  /* struct _prop_list_t * properties; */
822
  add_field_decl (objc_prop_list_ptr, "properties", &chain);
823
 
824
  objc_finish_struct (objc_v2_category_template, decls);
825
}
826
 
827
/* NOTE --- Decls, Identifiers, Names etc. --- */
828
 
829
/* This routine is given a name and returns a matching extern variable
830
   if one is found.  */
831
 
832
static tree
833
hash_name_lookup (hash *hashlist, tree name)
834
{
835
  hash target;
836
 
837
  target = hashlist[IDENTIFIER_HASH_VALUE (name) % SIZEHASHTABLE];
838
 
839
  while (target)
840
    {
841
      if (name == DECL_NAME (target->key))
842
        return target->key;
843
 
844
      target = target->next;
845
    }
846
  return 0;
847
}
848
 
849
/* This routine is given an extern variable and enters it in its hash
850
   table.  Note that hashing is done on its inner IDENTIFIER_NODE
851
   node.  */
852
 
853
static void
854
hash_name_enter (hash *hashlist, tree id)
855
{
856
  hash obj;
857
  int slot = IDENTIFIER_HASH_VALUE (DECL_NAME (id)) % SIZEHASHTABLE;
858
 
859
  obj = ggc_alloc_hashed_entry ();
860
  obj->list = 0;
861
  obj->next = hashlist[slot];
862
  obj->key = id;
863
 
864
  hashlist[slot] = obj;         /* append to front */
865
}
866
 
867
/* Create a declaration "extern <type> <name>;"
868
   The var will need to be finalized (e.g. by calling finish_var_decl()).  */
869
 
870
static tree
871
create_extern_decl (tree type, const char *name)
872
{
873
  tree id = get_identifier (name);
874
  tree var = hash_name_lookup (extern_names, id);
875
  if (var)
876
      return var;
877
  /* New name. */
878
  var = start_var_decl (type, name);
879
  TREE_STATIC (var) = 0;
880
  DECL_EXTERNAL (var) = 1;
881
  TREE_PUBLIC (var) = 1;
882
  hash_name_enter (extern_names, var);
883
  return var;
884
}
885
 
886
/* Create a globally visible definition for variable NAME of a given TYPE. The
887
   finish_var_decl() routine will need to be called on it afterwards.  */
888
 
889
static tree
890
create_global_decl (tree type, const char *name)
891
{
892
  tree id = get_identifier (name);
893
  tree var = hash_name_lookup (extern_names, id);
894
  if (var)
895
    {
896
      DECL_EXTERNAL (var) = 0;
897
      TREE_STATIC (var) = 1;
898
    }
899
  else
900
    {
901
      var = start_var_decl (type, name);
902
      hash_name_enter (extern_names, var);
903
    }
904
  TREE_PUBLIC (var) = 1;
905
  return var;
906
}
907
 
908
/* Create a symbol with __attribute__ ((visibility ("hidden")))
909
   attribute (private extern).  */
910
 
911
static tree
912
create_hidden_decl (tree type, const char *name)
913
{
914
    tree decl = create_global_decl (type, name);
915
    DECL_VISIBILITY (decl) = VISIBILITY_HIDDEN;
916
    DECL_VISIBILITY_SPECIFIED (decl) = 1;
917
    return decl;
918
}
919
 
920
/* Irritatingly, we have a different superclass field name for ABI=2.  */
921
/* PS/TODO: The field name does not matter, it is only used internally
922
   by the compiler.  We can rename it to whatever we want. ;-) */
923
 
924
static tree
925
next_runtime_abi_02_super_superclassfield_id (void)
926
{
927
  /* TODO: Simplify.  Just always return get_identifier ("cls"), or at
928
     most look it once at startup then always return it.  */
929
  if (!super_superclassfield_id)
930
    super_superclassfield_id = get_identifier ("cls");
931
  return super_superclassfield_id;
932
}
933
 
934
static tree
935
next_runtime_abi_02_class_decl (tree klass)
936
{
937
  tree decl;
938
  char buf[BUFSIZE];
939
  snprintf (buf, BUFSIZE, "OBJC_CLASS_$_%s",
940
            IDENTIFIER_POINTER (CLASS_NAME (klass)));
941
  /* ObjC2 classes are extern visible.  */
942
  decl = create_global_decl (objc_v2_class_template, buf);
943
  OBJCMETA (decl, objc_meta, meta_class);
944
  return decl;
945
}
946
 
947
static tree
948
next_runtime_abi_02_metaclass_decl (tree klass)
949
{
950
  tree decl;
951
  char buf[BUFSIZE];
952
  snprintf (buf, BUFSIZE, "OBJC_METACLASS_$_%s",
953
            IDENTIFIER_POINTER (CLASS_NAME (klass)));
954
  /* ObjC2 classes are extern visible.  */
955
  decl = create_global_decl (objc_v2_class_template, buf);
956
  OBJCMETA (decl, objc_meta, meta_metaclass);
957
  return decl;
958
}
959
 
960
static tree
961
next_runtime_abi_02_category_decl (tree klass)
962
{
963
  tree decl;
964
  char buf[BUFSIZE];
965
  snprintf (buf, BUFSIZE, "_OBJC_Category_%s_on_%s",
966
            IDENTIFIER_POINTER (CLASS_SUPER_NAME (klass)),
967
            IDENTIFIER_POINTER (CLASS_NAME (klass)));
968
  decl = start_var_decl (objc_v2_category_template, buf);
969
  OBJCMETA (decl, objc_meta, meta_category);
970
  return decl;
971
}
972
 
973
static tree
974
next_runtime_abi_02_protocol_decl (tree p)
975
{
976
  tree decl;
977
  char buf[BUFSIZE];
978
 
979
  /* static struct _objc_protocol _OBJC_Protocol_<mumble>; */
980
  snprintf (buf, BUFSIZE, "_OBJC_Protocol_%s",
981
            IDENTIFIER_POINTER (PROTOCOL_NAME (p)));
982
  decl = start_var_decl (objc_v2_protocol_template, buf);
983
  OBJCMETA (decl, objc_meta, meta_protocol);
984
  return decl;
985
}
986
 
987
static tree
988
next_runtime_abi_02_string_decl (tree type, const char *name,  string_section where)
989
{
990
  tree var = start_var_decl (type, name);
991
  switch (where)
992
    {
993
      case class_names:
994
        OBJCMETA (var, objc_meta, meta_class_name);
995
        break;
996
      case meth_var_names:
997
        OBJCMETA (var, objc_meta, meta_meth_name);
998
        break;
999
      case meth_var_types:
1000
        OBJCMETA (var, objc_meta, meta_meth_type);
1001
        break;
1002
      case prop_names_attr:
1003
        OBJCMETA (var, objc_meta, meta_prop_name_attr);
1004
        break;
1005
      default:
1006
        OBJCMETA (var, objc_meta, meta_base);
1007
        break;
1008
    }
1009
  return var;
1010
}
1011
 
1012
/* NOTE --- entry --- */
1013
 
1014
typedef struct GTY(()) ident_data_tuple {
1015
  tree ident;
1016
  tree data;
1017
} ident_data_tuple ;
1018
DEF_VEC_O(ident_data_tuple);
1019
DEF_VEC_ALLOC_O(ident_data_tuple, gc);
1020
 
1021
/* This routine creates a file scope static variable of type 'Class'
1022
   to hold the address of a class.  */
1023
 
1024
static tree
1025
build_v2_class_reference_decl (tree ident)
1026
{
1027
  tree decl;
1028
  char buf[BUFSIZE];
1029
 
1030
  snprintf (buf, BUFSIZE, "_OBJC_ClassRef_%s", IDENTIFIER_POINTER (ident));
1031
  decl = start_var_decl (objc_class_type, buf);
1032
  OBJCMETA (decl, objc_meta, meta_class_ref);
1033
  return decl;
1034
}
1035
 
1036
/* This routine builds a class refs entry for each class name used.
1037
   Initially, a (static-ref, IDENT) tuple is added to the list.  The
1038
   ident is replaced with address of the class metadata (of type
1039
   'Class') in the output routine.  */
1040
 
1041
static GTY (()) VEC (ident_data_tuple, gc) * classrefs;
1042
 
1043
static tree
1044
objc_v2_get_class_reference (tree ident)
1045
{
1046
  tree decl;
1047
  ident_data_tuple e;
1048
  if (classrefs)
1049
    {
1050
      int count;
1051
      ident_data_tuple *ref;
1052
      FOR_EACH_VEC_ELT (ident_data_tuple, classrefs, count, ref)
1053
        {
1054
          if (ref->ident == ident)
1055
            {
1056
              if (!ref->data)
1057
                ref->data = build_v2_class_reference_decl (ident);
1058
              return ref->data;
1059
            }
1060
        }
1061
    }
1062
  else
1063
    /* Somewhat arbitrary initial provision.  */
1064
    classrefs = VEC_alloc (ident_data_tuple, gc, 16);
1065
 
1066
  /* We come here if we don't find the entry - or if the table was yet
1067
     to be created.  */
1068
  decl = build_v2_class_reference_decl (ident);
1069
  e.ident = ident;
1070
  e.data = decl;
1071
  VEC_safe_push (ident_data_tuple, gc, classrefs, &e);
1072
  return decl;
1073
}
1074
 
1075
static tree
1076
next_runtime_abi_02_get_class_reference (tree ident)
1077
{
1078
  if (!flag_zero_link)
1079
    return objc_v2_get_class_reference (ident);
1080
  else
1081
    {
1082
      /* We fall back to using objc_getClass ().  */
1083
      VEC(tree,gc) *vec =  VEC_alloc (tree, gc, 1);
1084
      tree t;
1085
      /* ??? add_class_reference (ident); - is pointless, since the
1086
         system lib does not export the equivalent symbols.  Maybe we
1087
         need to build a class ref anyway.  */
1088
      t = my_build_string_pointer (IDENTIFIER_LENGTH (ident) + 1,
1089
                                   IDENTIFIER_POINTER (ident));
1090
      VEC_quick_push (tree, vec, t);
1091
      t = build_function_call_vec (input_location, objc_get_class_decl,
1092
                                   vec, NULL);
1093
      VEC_free (tree, gc, vec);
1094
      return t;
1095
    }
1096
}
1097
 
1098
/* Used by build_function_type_for_method.  Append the types for
1099
   receiver & _cmd at the start of a method argument list to ARGTYPES.
1100
   CONTEXT is either METHOD_DEF or METHOD_REF, saying whether we are
1101
   trying to define a method or call one.  SUPERFLAG says this is for a
1102
   send to super.  METH may be NULL, in the case that there is no
1103
   prototype.  */
1104
 
1105
static void
1106
next_runtime_abi_02_get_arg_type_list_base (VEC(tree,gc) **argtypes, tree meth,
1107
                                            int context, int superflag)
1108
{
1109
  tree receiver_type;
1110
 
1111
  if (superflag)
1112
    receiver_type = objc_super_type;
1113
  else if (context == METHOD_DEF && TREE_CODE (meth) == INSTANCE_METHOD_DECL)
1114
    receiver_type = objc_instance_type;
1115
  else
1116
    receiver_type = objc_object_type;
1117
 
1118
  VEC_safe_push (tree, gc, *argtypes, receiver_type);
1119
  /* Selector type - will eventually change to `int'.  */
1120
  VEC_safe_push (tree, gc, *argtypes,
1121
                 (superflag
1122
                  ? objc_v2_super_selector_type
1123
                  : objc_v2_selector_type));
1124
}
1125
 
1126
/* TODO: Merge this with the message refs.  */
1127
static tree
1128
build_selector_reference_decl (tree ident)
1129
{
1130
  tree decl;
1131
  char *t, buf[BUFSIZE];
1132
 
1133
  snprintf (buf, BUFSIZE, "_OBJC_SelRef_%s", IDENTIFIER_POINTER (ident));
1134
  t = buf;
1135
  while (*t)
1136
    {
1137
      if (*t==':')
1138
        *t = '$'; /* Underscore would clash between foo:bar and foo_bar.  */
1139
      t++;
1140
    }
1141
  decl = start_var_decl (objc_selector_type, buf);
1142
  OBJCMETA (decl, objc_meta, meta_sel_refs);
1143
  return decl;
1144
}
1145
 
1146
static tree
1147
next_runtime_abi_02_build_selector_reference (location_t loc ATTRIBUTE_UNUSED,
1148
                                              tree ident,
1149
                                              tree proto ATTRIBUTE_UNUSED)
1150
{
1151
  tree *chain = &sel_ref_chain;
1152
  tree expr;
1153
 
1154
  while (*chain)
1155
    {
1156
      if (TREE_VALUE (*chain) == ident)
1157
        return TREE_PURPOSE (*chain);
1158
 
1159
      chain = &TREE_CHAIN (*chain);
1160
    }
1161
 
1162
  expr = build_selector_reference_decl (ident);
1163
  *chain = tree_cons (expr, ident, NULL_TREE);
1164
 
1165
  return expr;
1166
}
1167
 
1168
/* Declare a variable of type 'struct message_ref_t'. */
1169
/* This will be finished in build_v2_message_ref_translation_table ().
1170
   We take an idea from LLVM in making the names a bit more connected
1171
   and thus the asm more readable.  */
1172
 
1173
static tree
1174
build_v2_message_reference_decl (tree sel_name, tree message_func_ident)
1175
{
1176
  tree decl;
1177
  char buf[BUFSIZE], *t;
1178
  int offset = 12;
1179
 
1180
  /* Skip past the objc_msgSend it's the same for all...  */
1181
  if (IDENTIFIER_POINTER (message_func_ident)[offset] == '_')
1182
    offset++;
1183
 
1184
  snprintf (buf, BUFSIZE, "_OBJC_MsgRef_%s_%s",
1185
            &(IDENTIFIER_POINTER (message_func_ident)[offset]),
1186
            IDENTIFIER_POINTER (sel_name));
1187
  t = buf;
1188
  while (*t)
1189
    {
1190
      if (*t==':')
1191
        *t = '$'; /* Underscore would clash between foo:bar and foo_bar.  */
1192
      t++;
1193
    }
1194
  decl = start_var_decl (objc_v2_message_ref_template, buf);
1195
  OBJCMETA (decl, objc_meta, meta_mref);
1196
  return decl;
1197
}
1198
 
1199
typedef struct GTY(()) msgref_entry {
1200
  tree func;
1201
  tree selname;
1202
  tree refdecl;
1203
} msgref_entry;
1204
DEF_VEC_O(msgref_entry);
1205
DEF_VEC_ALLOC_O(msgref_entry, gc);
1206
 
1207
static GTY (()) VEC (msgref_entry, gc) * msgrefs;
1208
 
1209
/* Build the list of (objc_msgSend_fixup_xxx, selector name), used
1210
   later on to initialize the table of 'struct message_ref_t'
1211
   elements.  */
1212
 
1213
static tree
1214
build_v2_selector_messenger_reference (tree sel_name, tree message_func_decl)
1215
{
1216
  tree decl;
1217
  msgref_entry e;
1218
  if (msgrefs)
1219
    {
1220
      int count;
1221
      msgref_entry *ref;
1222
      FOR_EACH_VEC_ELT (msgref_entry, msgrefs, count, ref)
1223
        if (ref->func == message_func_decl && ref->selname == sel_name)
1224
          return ref->refdecl;
1225
    }
1226
  else
1227
    /* Somewhat arbitrary initial provision.  */
1228
    msgrefs = VEC_alloc (msgref_entry, gc, 32);
1229
 
1230
  /* We come here if we don't find a match or at the start.  */
1231
  decl = build_v2_message_reference_decl (sel_name,
1232
                                          DECL_NAME (message_func_decl));
1233
  e.func = message_func_decl;
1234
  e.selname = sel_name;
1235
  e.refdecl = decl;
1236
  VEC_safe_push (msgref_entry, gc, msgrefs, &e);
1237
  return decl;
1238
}
1239
 
1240
static tree
1241
build_v2_protocollist_ref_decl (tree protocol)
1242
{
1243
  tree decl;
1244
  tree protocol_ident = PROTOCOL_NAME (protocol);
1245
  char buf[BUFSIZE];
1246
 
1247
  snprintf (buf, BUFSIZE, "_OBJC_ProtocolRef_%s",
1248
            IDENTIFIER_POINTER (protocol_ident));
1249
  /* TODO: other compiler versions make these hidden & weak.  */
1250
  decl = create_global_decl (objc_protocol_type, buf);
1251
  /* Let optimizer know that this decl is not removable.  */
1252
  DECL_PRESERVE_P (decl) = 1;
1253
  OBJCMETA (decl, objc_meta, meta_proto_ref);
1254
  return decl;
1255
}
1256
 
1257
typedef struct GTY(()) prot_list_entry {
1258
  tree id;
1259
  tree refdecl;
1260
} prot_list_entry;
1261
DEF_VEC_O(prot_list_entry);
1262
DEF_VEC_ALLOC_O(prot_list_entry, gc);
1263
static GTY (()) VEC (prot_list_entry, gc) * protrefs;
1264
 
1265
static tree
1266
objc_v2_get_protocol_reference (tree ident)
1267
{
1268
  tree decl;
1269
  prot_list_entry e;
1270
  if (protrefs)
1271
    {
1272
      int count;
1273
      prot_list_entry *ref;
1274
      FOR_EACH_VEC_ELT (prot_list_entry, protrefs, count, ref)
1275
        {
1276
          if (ref->id == ident)
1277
            {
1278
              if (!ref->refdecl)
1279
                ref->refdecl = build_v2_protocollist_ref_decl (ident);
1280
              return ref->refdecl;
1281
            }
1282
        }
1283
    }
1284
  else
1285
    /* Somewhat arbitrary initial provision.  */
1286
    protrefs = VEC_alloc (prot_list_entry, gc, 32);
1287
 
1288
  /* We come here if we don't find the entry - or if the table was yet
1289
     to be created.  */
1290
  decl = build_v2_protocollist_ref_decl (ident);
1291
  e.id = ident;
1292
  e.refdecl = decl;
1293
  VEC_safe_push (prot_list_entry, gc, protrefs, &e);
1294
  return decl;
1295
}
1296
 
1297
static tree
1298
next_runtime_abi_02_get_protocol_reference (location_t loc ATTRIBUTE_UNUSED,
1299
                                            tree p)
1300
{
1301
  if (!PROTOCOL_FORWARD_DECL (p))
1302
    PROTOCOL_FORWARD_DECL (p) = next_runtime_abi_02_protocol_decl (p);
1303
 
1304
  return objc_v2_get_protocol_reference (p);
1305
}
1306
 
1307
/* This routine returns the ivar declaration, if component is a valid
1308
   ivar field; NULL_TREE otherwise. On finding an ivar, it also
1309
   returns the class name in CLASS.  */
1310
 
1311
static tree
1312
objc_is_ivar (tree expr, tree component, tree *klass)
1313
{
1314
  tree field = NULL_TREE;
1315
  tree basetype = TYPE_MAIN_VARIANT (TREE_TYPE (expr));
1316
 
1317
  if (TREE_CODE (basetype) == RECORD_TYPE
1318
      && TYPE_HAS_OBJC_INFO (basetype) && TYPE_OBJC_INTERFACE (basetype))
1319
    {
1320
      *klass = lookup_interface (OBJC_TYPE_NAME (basetype));
1321
      if (*klass)
1322
        {
1323
          do
1324
            {
1325
              tree ivar_chain = CLASS_RAW_IVARS (*klass);
1326
              if (ivar_chain)
1327
                {
1328
                  field = is_ivar (ivar_chain, component);
1329
                  if (field != NULL_TREE)
1330
                    break;
1331
                }
1332
              *klass = lookup_interface (CLASS_SUPER_NAME (*klass));
1333
            }
1334
          while (*klass);
1335
        }
1336
    }
1337
  return field;
1338
}
1339
 
1340
static void
1341
create_ivar_offset_name (char *buf, tree class_name, tree field_decl)
1342
{
1343
  tree fname = DECL_NAME (field_decl);
1344
 
1345
  sprintf (buf, "OBJC_IVAR_$_%s.%s", IDENTIFIER_POINTER (class_name),
1346
           IDENTIFIER_POINTER (fname));
1347
  return;
1348
}
1349
 
1350
/* This routine generates new abi's ivar reference tree.  It amounts
1351
   to generating *(TYPE*)((char*)pObj + OFFSET_IVAR) when we normally
1352
   generate pObj->IVAR.  OFFSET_IVAR is an 'extern' variable holding
1353
   the offset for 'IVAR' field.  TYPE is type of IVAR field.  */
1354
 
1355
static tree
1356
objc_v2_build_ivar_ref (tree datum, tree component)
1357
{
1358
  tree field, ref, class_name, offset, ftype, expr;
1359
  char var_offset_name[512];
1360
 
1361
  field = objc_is_ivar (datum, component, &class_name);
1362
  if (!field)
1363
    return NULL_TREE;
1364
 
1365
  /* This routine only handles non-bitfield fields */
1366
  /* DECL_INITIAL macro is set to width of bitfield and can be relied
1367
     on to check for bitfield ivars.  Note that I cannot rely on
1368
     DECL_BIT_FIELD macro because it is only set when the whole struct
1369
     is seen (at finish_struct) and not when the ivar chain is
1370
     built.  */
1371
  if (DECL_INITIAL (field))
1372
    return NULL_TREE;
1373
 
1374
  create_ivar_offset_name (var_offset_name, CLASS_NAME (class_name),  field);
1375
 
1376
  offset = create_extern_decl (TREE_TYPE (size_zero_node), var_offset_name);
1377
 
1378
  ftype = TREE_TYPE (field);
1379
 
1380
  /* (char*)datum */
1381
  expr = build_c_cast (input_location,
1382
                       string_type_node, build_fold_addr_expr (datum));
1383
 
1384
  /* (char*)datum + offset */
1385
  expr = fold_build_pointer_plus_loc (input_location, expr, offset);
1386
 
1387
  /* (ftype*)((char*)datum + offset) */
1388
  expr = build_c_cast (input_location, build_pointer_type (ftype), expr);
1389
 
1390
  /* Finally: *(ftype*)((char*)datum + offset) */
1391
  ref = build_indirect_ref (input_location, expr, RO_UNARY_STAR);
1392
 
1393
  /* We must set type of the resulting expression to be the same as
1394
     the field type. This is because, build_indirect_ref (...)
1395
     rebuilds the type which may result in lost information; as in the
1396
     case of protocol-qualified types (id <protocol> ).  */
1397
  TREE_TYPE (ref) = ftype;
1398
 
1399
  if (TREE_READONLY (datum) || TREE_READONLY (field))
1400
    TREE_READONLY (ref) = 1;
1401
 
1402
  if (TREE_THIS_VOLATILE (datum) || TREE_THIS_VOLATILE (field))
1403
    TREE_THIS_VOLATILE (ref) = 1;
1404
 
1405
  if (TREE_DEPRECATED (field))
1406
    warn_deprecated_use (field, NULL_TREE);
1407
 
1408
  return ref;
1409
}
1410
 
1411
/* IVAR refs are made via an externally referenceable offset and built
1412
   on the fly.  That is, unless they refer to (private) fields in  the
1413
   class stucture.  */
1414
static tree
1415
next_runtime_abi_02_build_ivar_ref (location_t loc ATTRIBUTE_UNUSED,
1416
                                   tree base, tree id)
1417
{
1418
  tree ivar;
1419
  if ((ivar = objc_v2_build_ivar_ref (base, id)))
1420
    return ivar;
1421
  return objc_build_component_ref (base, id);
1422
}
1423
 
1424
/* [super ...] references are listed here (and built into a table at
1425
   meta -data emit time).  */
1426
static tree
1427
build_v2_superclass_ref_decl (tree ident, bool inst)
1428
{
1429
  tree decl;
1430
  char buf[BUFSIZE];
1431
 
1432
  snprintf (buf, BUFSIZE, "_OBJC_%sSuperRef_%s", (inst?"":"Meta"),
1433
            IDENTIFIER_POINTER (ident));
1434
  decl = start_var_decl (objc_class_type, buf);
1435
  OBJCMETA (decl, objc_meta, meta_superclass_ref);
1436
  return decl;
1437
}
1438
 
1439
static GTY (()) VEC (ident_data_tuple, gc) * class_super_refs;
1440
static GTY (()) VEC (ident_data_tuple, gc) * metaclass_super_refs;
1441
 
1442
static tree
1443
next_runtime_abi_02_get_class_super_ref (location_t loc ATTRIBUTE_UNUSED,
1444
                                         struct imp_entry *imp, bool inst_meth)
1445
{
1446
  tree decl;
1447
  ident_data_tuple e;
1448
  tree id = CLASS_NAME (imp->imp_context);
1449
  VEC (ident_data_tuple, gc) *list = inst_meth  ? class_super_refs
1450
                                                : metaclass_super_refs;
1451
 
1452
  if (list)
1453
    {
1454
      int count;
1455
      ident_data_tuple *ref;
1456
      FOR_EACH_VEC_ELT (ident_data_tuple, list, count, ref)
1457
        {
1458
          if (ref->ident == id)
1459
            {
1460
              if (!ref->data)
1461
                ref->data = build_v2_superclass_ref_decl (id, inst_meth);
1462
              return ref->data;
1463
            }
1464
        }
1465
    }
1466
  else
1467
    {
1468
      /* Somewhat arbitrary initial provision.  */
1469
      if (inst_meth)
1470
        list = class_super_refs = VEC_alloc (ident_data_tuple, gc, 16);
1471
      else
1472
        list = metaclass_super_refs = VEC_alloc (ident_data_tuple, gc, 16);
1473
    }
1474
  /* We come here if we don't find the entry - or if the table was yet
1475
     to be created.  */
1476
  decl = build_v2_superclass_ref_decl (id, inst_meth);
1477
  e.ident = id;
1478
  e.data = decl;
1479
  VEC_safe_push (ident_data_tuple, gc, list, &e);
1480
  return decl;
1481
}
1482
 
1483
static tree
1484
next_runtime_abi_02_get_category_super_ref (location_t loc ATTRIBUTE_UNUSED,
1485
                                           struct imp_entry *imp, bool inst_meth)
1486
{
1487
  /* ??? is this OK when zero-link = true?  */
1488
  tree super_name = CLASS_SUPER_NAME (imp->imp_template);
1489
  tree super_class;
1490
 
1491
  if (!flag_zero_link)
1492
    {
1493
      super_class = objc_get_class_reference (CLASS_NAME (imp->imp_template));
1494
 
1495
      if (!inst_meth)
1496
 
1497
        /* If we are in a class method, we must retrieve the
1498
           _metaclass_ for the current class, pointed at by the
1499
           class's "isa" pointer.  The following assumes that "isa" is
1500
           the first ivar in a class (which it must be).  */
1501
           super_class =
1502
                build_indirect_ref (input_location,
1503
                                    build_c_cast (input_location,
1504
                                        build_pointer_type (objc_class_type),
1505
                                        super_class),
1506
                                    RO_UNARY_STAR);
1507
      return super_class;
1508
    }
1509
  /* ??? Do we need to add the class ref anway for zero-link?  */
1510
  /* else do it the slow way.  */
1511
  super_class = (inst_meth ? objc_get_class_decl : objc_get_meta_class_decl);
1512
  /* assemble_external (super_class); */
1513
  super_name = my_build_string_pointer (IDENTIFIER_LENGTH (super_name) + 1,
1514
                                        IDENTIFIER_POINTER (super_name));
1515
  /* super_class = objc_get{Meta}Class("CLASS_SUPER_NAME"); */
1516
  return build_function_call (input_location,
1517
                              super_class,
1518
                              build_tree_list (NULL_TREE, super_name));
1519
}
1520
 
1521
static tree
1522
next_runtime_abi_02_receiver_is_class_object (tree receiver)
1523
{
1524
  if (TREE_CODE (receiver) == VAR_DECL
1525
      && IS_CLASS (TREE_TYPE (receiver))
1526
      && classrefs
1527
      && VEC_length (ident_data_tuple, classrefs))
1528
    {
1529
      int count;
1530
      ident_data_tuple *ref;
1531
      /* The receiver is a variable created by build_class_reference_decl.  */
1532
      FOR_EACH_VEC_ELT (ident_data_tuple, classrefs, count, ref)
1533
        if (ref->data == receiver)
1534
          return ref->ident;
1535
    }
1536
  return NULL_TREE;
1537
}
1538
 
1539
/* Assign all arguments in VALUES which have side-effect to a temporary
1540
   and replaced that argument in VALUES list with the temporary. The
1541
   arguments will be passed to a function with FNTYPE.  */
1542
 
1543
static tree
1544
objc_copy_to_temp_side_effect_params (tree fntype, tree values)
1545
{
1546
  tree valtail;
1547
  function_args_iterator iter;
1548
 
1549
  /* Skip over receiver and the &_msf_ref types.  */
1550
  function_args_iter_init (&iter, fntype);
1551
  function_args_iter_next (&iter);
1552
  function_args_iter_next (&iter);
1553
 
1554
  for (valtail = values; valtail;
1555
       valtail = TREE_CHAIN (valtail), function_args_iter_next (&iter))
1556
    {
1557
      tree value = TREE_VALUE (valtail);
1558
      tree type = function_args_iter_cond (&iter);
1559
      if (type == NULL_TREE)
1560
        break;
1561
      if (!TREE_SIDE_EFFECTS (value))
1562
        continue;
1563
      /* To prevent re-evaluation.  */
1564
      value = save_expr (value);
1565
      add_stmt (value);
1566
      TREE_VALUE (valtail) = value;
1567
    }
1568
  return values;
1569
}
1570
 
1571
/* Build the new abi's messaging library call. It looks like:
1572
   (*_msg.messenger) (receiver, &_msg, ...) */
1573
 
1574
static tree
1575
build_v2_build_objc_method_call (int super_flag, tree method_prototype,
1576
                                 tree lookup_object, tree selector,
1577
                                 tree method_params,
1578
                                 bool check_for_nil)
1579
{
1580
  tree ret_val;
1581
  tree sender, rcv_p, t;
1582
  tree ret_type
1583
    = (method_prototype
1584
       ? TREE_VALUE (TREE_TYPE (method_prototype))
1585
       : objc_object_type);
1586
  tree ftype = build_function_type_for_method (ret_type, method_prototype,
1587
                                               METHOD_REF, super_flag);
1588
  tree sender_cast;
1589
 
1590
  if (method_prototype && METHOD_TYPE_ATTRIBUTES (method_prototype))
1591
    ftype = build_type_attribute_variant (
1592
              ftype, METHOD_TYPE_ATTRIBUTES (method_prototype));
1593
 
1594
  sender_cast = build_pointer_type (ftype);
1595
 
1596
  if (check_for_nil)
1597
    method_params = objc_copy_to_temp_side_effect_params (ftype,
1598
                                                          method_params);
1599
 
1600
  /* Get &message_ref_t.messenger.  */
1601
  sender = build_c_cast (input_location,
1602
                         build_pointer_type (super_flag
1603
                                             ? objc_v2_super_imp_type
1604
                                             : objc_v2_imp_type),
1605
                         selector);
1606
 
1607
  sender = build_indirect_ref (input_location, sender, RO_UNARY_STAR);
1608
 
1609
  rcv_p = (super_flag ? objc_super_type : objc_object_type);
1610
 
1611
  lookup_object = build_c_cast (input_location, rcv_p, lookup_object);
1612
 
1613
  /* Use SAVE_EXPR to avoid evaluating the receiver twice.  */
1614
  lookup_object = save_expr (lookup_object);
1615
 
1616
  method_params = tree_cons (NULL_TREE, lookup_object,
1617
                             tree_cons (NULL_TREE, selector,
1618
                                        method_params));
1619
  t = build3 (OBJ_TYPE_REF, sender_cast, sender, lookup_object, size_zero_node);
1620
  ret_val =  build_function_call (input_location, t, method_params);
1621
  if (check_for_nil)
1622
    {
1623
      /* receiver != nil ? ret_val : 0 */
1624
      tree ftree;
1625
      tree ifexp;
1626
 
1627
      if (TREE_CODE (ret_type) == RECORD_TYPE
1628
          || TREE_CODE (ret_type) == UNION_TYPE)
1629
        {
1630
          VEC(constructor_elt,gc) *rtt = NULL;
1631
          /* ??? CHECKME. hmmm..... think we need something more
1632
             here.  */
1633
          CONSTRUCTOR_APPEND_ELT (rtt, NULL_TREE, NULL_TREE);
1634
          ftree = objc_build_constructor (ret_type, rtt);
1635
        }
1636
      else
1637
        ftree = fold_convert (ret_type, integer_zero_node);
1638
 
1639
      ifexp = build_binary_op (input_location, NE_EXPR,
1640
                               lookup_object,
1641
                               fold_convert (rcv_p, integer_zero_node), 1);
1642
 
1643
#ifdef OBJCPLUS
1644
      ret_val = build_conditional_expr (ifexp, ret_val, ftree, tf_warning_or_error);
1645
#else
1646
     /* ??? CHECKME.   */
1647
      ret_val = build_conditional_expr (input_location,
1648
                                        ifexp, 1,
1649
                                        ret_val, NULL_TREE,
1650
                                        ftree, NULL_TREE);
1651
#endif
1652
    }
1653
  return ret_val;
1654
}
1655
 
1656
static tree
1657
next_runtime_abi_02_build_objc_method_call (location_t loc,
1658
                                            tree method_prototype,
1659
                                            tree receiver,
1660
                                            tree rtype,
1661
                                            tree sel_name,
1662
                                            tree method_params,
1663
                                            int super)
1664
{
1665
  tree ret_type, selector;
1666
  tree message_func_decl;
1667
  bool check_for_nil = flag_objc_nilcheck;
1668
 
1669
  ret_type = method_prototype
1670
             ? TREE_VALUE (TREE_TYPE (method_prototype))
1671
             : objc_object_type;
1672
 
1673
  /* Do we need to check for nil receivers ? */
1674
  /* For now, message sent to classes need no nil check.  In the
1675
      future, class declaration marked as weak_import must be nil
1676
      checked.  */
1677
  if (super
1678
      || (TREE_CODE (receiver) == VAR_DECL
1679
          && TREE_TYPE (receiver) == objc_class_type))
1680
    check_for_nil = false;
1681
 
1682
  if (!targetm.calls.struct_value_rtx (0, 0)
1683
          && (TREE_CODE (ret_type) == RECORD_TYPE
1684
              || TREE_CODE (ret_type) == UNION_TYPE)
1685
          && targetm.calls.return_in_memory (ret_type, 0))
1686
    {
1687
      if (super)
1688
        message_func_decl = umsg_id_super2_stret_fixup_decl;
1689
      else
1690
        message_func_decl = objc_is_id (rtype)
1691
                            ? umsg_id_stret_fixup_decl
1692
                            : umsg_stret_fixup_decl;
1693
    }
1694
  else
1695
    {
1696
      if (super)
1697
        message_func_decl = umsg_id_super2_fixup_decl;
1698
      else
1699
        message_func_decl = objc_is_id (rtype)
1700
                            ? umsg_id_fixup_decl
1701
                            : umsg_fixup_decl;
1702
    }
1703
 
1704
  selector = build_v2_selector_messenger_reference (sel_name,
1705
                                                      message_func_decl);
1706
 
1707
  /* selector = &_msg; */
1708
  selector = build_unary_op (loc, ADDR_EXPR, selector, 0);
1709
 
1710
  selector = build_c_cast (loc, (super ? objc_v2_super_selector_type
1711
                                       : objc_v2_selector_type),
1712
                           selector);
1713
 
1714
  /* (*_msg.messenger) (receiver, &_msg, ...); */
1715
  return build_v2_build_objc_method_call (super, method_prototype,
1716
                                          receiver, selector,
1717
                                          method_params, check_for_nil);
1718
}
1719
 
1720
/* NOTE --- Constant String Class Stuff --- */
1721
 
1722
static bool
1723
next_runtime_abi_02_setup_const_string_class_decl (void)
1724
{
1725
  if (!constant_string_global_id)
1726
    {
1727
      /* Hopefully, this should not represent a serious limitation.  */
1728
      char buf[BUFSIZE];
1729
      snprintf (buf, BUFSIZE, "OBJC_CLASS_$_%s", constant_string_class_name);
1730
      constant_string_global_id = get_identifier (buf);
1731
    }
1732
 
1733
  string_class_decl = lookup_name (constant_string_global_id);
1734
 
1735
  /* In OBJC2 abi, constant string class reference refers to class
1736
     name for NSConstantString class.  This declaration may not be
1737
     available yet (in fact it is not in most cases).  So, declare an
1738
     extern OBJC_CLASS_$_NSConstantString in its place. */
1739
  if (!string_class_decl)
1740
    string_class_decl =
1741
        create_extern_decl (objc_v2_class_template,
1742
                            IDENTIFIER_POINTER (constant_string_global_id));
1743
 
1744
  return (string_class_decl != NULL_TREE);
1745
}
1746
 
1747
static tree
1748
next_runtime_abi_02_build_const_string_constructor (location_t loc, tree string,
1749
                                                   int length)
1750
{
1751
  tree constructor, fields, var;
1752
  VEC(constructor_elt,gc) *v = NULL;
1753
 
1754
  /* NeXT: (NSConstantString *) & ((__builtin_ObjCString) { isa, string, length }) */
1755
  fields = TYPE_FIELDS (internal_const_str_type);
1756
  CONSTRUCTOR_APPEND_ELT (v, fields,
1757
                          build_unary_op (loc, ADDR_EXPR, string_class_decl, 0));
1758
 
1759
  fields = DECL_CHAIN (fields);
1760
  CONSTRUCTOR_APPEND_ELT (v, fields,
1761
                          build_unary_op (loc, ADDR_EXPR, string, 1));
1762
 
1763
  /* ??? check if this should be long.  */
1764
  fields = DECL_CHAIN (fields);
1765
  CONSTRUCTOR_APPEND_ELT (v, fields, build_int_cst (NULL_TREE, length));
1766
  constructor = objc_build_constructor (internal_const_str_type, v);
1767
 
1768
  var = build_decl (input_location, CONST_DECL, NULL, TREE_TYPE (constructor));
1769
  DECL_INITIAL (var) = constructor;
1770
  TREE_STATIC (var) = 1;
1771
  DECL_CONTEXT (var) = NULL;
1772
  OBJCMETA (var, objc_meta, meta_const_str);
1773
  return var;
1774
}
1775
 
1776
/* NOTE --- NeXT V2 Metadata templates --- */
1777
 
1778
/* This routine builds the following type:
1779
   struct _prop_t
1780
   {
1781
     const char * const name;                   // property name
1782
     const char * const attributes;             // comma-delimited, encoded,
1783
                                                // property attributes
1784
   };
1785
*/
1786
 
1787
static tree
1788
build_v2_property_template (void)
1789
{
1790
  tree prop_record;
1791
  tree decls, *chain = NULL;
1792
 
1793
  prop_record = objc_start_struct (get_identifier ("_prop_t"));
1794
  /* const char * name */
1795
  decls = add_field_decl (string_type_node, "name", &chain);
1796
 
1797
  /* const char * attribute */
1798
  add_field_decl (string_type_node, "attribute", &chain);
1799
 
1800
  objc_finish_struct (prop_record, decls);
1801
  return prop_record;
1802
}
1803
 
1804
/* struct ivar_t
1805
   {
1806
     unsigned long int *offset;
1807
     char *name;
1808
     char *type;
1809
     uint32_t alignment;
1810
     uint32_t size;
1811
   };
1812
*/
1813
 
1814
static tree
1815
build_v2_ivar_t_template (void)
1816
{
1817
  tree objc_ivar_id, objc_ivar_record;
1818
  tree decls, *chain = NULL;
1819
 
1820
  objc_ivar_id = get_identifier ("_ivar_t");
1821
  objc_ivar_record = objc_start_struct (objc_ivar_id);
1822
 
1823
  /* unsigned long int *offset; */
1824
  decls = add_field_decl (build_pointer_type
1825
                           (TREE_TYPE (size_zero_node)), "offset", &chain);
1826
 
1827
  /* char *name; */
1828
  add_field_decl (string_type_node, "name", &chain);
1829
 
1830
  /* char *type; */
1831
  add_field_decl (string_type_node, "type", &chain);
1832
 
1833
  /* uint32_t alignment; */
1834
  add_field_decl (integer_type_node, "alignment", &chain);
1835
 
1836
  /* uint32_t size; */
1837
  add_field_decl (integer_type_node, "size", &chain);
1838
 
1839
  objc_finish_struct (objc_ivar_record, decls);
1840
  return objc_ivar_record;
1841
}
1842
 
1843
static void
1844
build_metadata_templates (void)
1845
{
1846
 
1847
  if (!objc_method_template)
1848
    objc_method_template = build_method_template ();
1849
 
1850
  if (!objc_v2_property_template)
1851
    objc_v2_property_template = build_v2_property_template ();
1852
 
1853
  if (!objc_v2_ivar_template)
1854
    objc_v2_ivar_template = build_v2_ivar_t_template ();
1855
 
1856
}
1857
 
1858
/* NOTE --- Output NeXT V2 Metadata --- */
1859
 
1860
/* Routine builds name of Interface's main meta-data of type class_t. */
1861
 
1862
static char *
1863
objc_build_internal_classname (tree ident, bool metaclass)
1864
{
1865
  static char string[512];
1866
  snprintf (string, 512, "%s_%s", metaclass ? "OBJC_METACLASS_$"
1867
                                            : "OBJC_CLASS_$",
1868
            IDENTIFIER_POINTER (ident));
1869
  return string;
1870
}
1871
 
1872
/* Build the name for object of type struct class_ro_t */
1873
 
1874
static const char *
1875
newabi_append_ro (const char *name)
1876
{
1877
  const char *dollar;
1878
  char *p;
1879
  static char string[BUFSIZE];
1880
  dollar = strchr (name, '$');
1881
  gcc_assert (dollar);
1882
  p = string;
1883
  *p = '_'; p++;
1884
  strncpy (p, name, (int)(dollar - name));
1885
  p += (int)(dollar - name);
1886
  sprintf (p, "RO_%s", dollar);
1887
  return string;
1888
}
1889
 
1890
/* Build the struct message_ref_t msg =
1891
               {objc_msgSend_fixup_xxx, @selector(func)}
1892
   table.  */
1893
 
1894
static
1895
void build_v2_message_ref_translation_table (void)
1896
{
1897
  int count;
1898
  msgref_entry *ref;
1899
 
1900
  if (!msgrefs || !VEC_length (msgref_entry,msgrefs))
1901
    return;
1902
 
1903
  FOR_EACH_VEC_ELT (msgref_entry, msgrefs, count, ref)
1904
    {
1905
      VEC(constructor_elt,gc) *initializer;
1906
      tree expr, constructor;
1907
      tree struct_type = TREE_TYPE (ref->refdecl);
1908
      location_t loc = DECL_SOURCE_LOCATION (ref->refdecl);
1909
 
1910
      initializer = NULL;
1911
      /* First 'IMP messenger' field...  */
1912
      expr = build_unary_op (loc, ADDR_EXPR, ref->func, 0);
1913
      expr = convert (objc_v2_imp_type, expr);
1914
      CONSTRUCTOR_APPEND_ELT (initializer, NULL_TREE, expr);
1915
 
1916
      /* ... then 'SEL name' field.  */
1917
      expr = build_selector (ref->selname);
1918
      CONSTRUCTOR_APPEND_ELT (initializer, NULL_TREE, expr);
1919
      constructor = objc_build_constructor (struct_type, initializer);
1920
      finish_var_decl (ref->refdecl, constructor);
1921
    }
1922
}
1923
 
1924
/* Build decl = initializer; for each externally visible class
1925
   reference.  */
1926
 
1927
static void
1928
build_v2_classrefs_table (void)
1929
{
1930
  int count;
1931
  ident_data_tuple *ref;
1932
 
1933
  if (!classrefs || !VEC_length (ident_data_tuple, classrefs))
1934
    return;
1935
 
1936
  FOR_EACH_VEC_ELT (ident_data_tuple, classrefs, count, ref)
1937
    {
1938
      tree expr = ref->ident;
1939
      tree decl = ref->data;
1940
      /* Interface with no implementation and yet one of its messages
1941
         has been used. Need to generate a full address-of tree for it
1942
         here.  */
1943
      if (TREE_CODE (expr) == IDENTIFIER_NODE)
1944
        {
1945
          const char *name = objc_build_internal_classname (expr, false);
1946
          expr = create_extern_decl (objc_v2_class_template, name);
1947
          expr = convert (objc_class_type, build_fold_addr_expr (expr));
1948
        }
1949
      /* The runtime wants this, even if it appears unused, so we must force the
1950
         output.
1951
      DECL_PRESERVE_P (decl) = 1; */
1952
      finish_var_decl (decl, expr);
1953
    }
1954
}
1955
 
1956
/* Build decl = initializer; for each externally visible super class
1957
   reference.  */
1958
 
1959
static void
1960
build_v2_super_classrefs_table (bool metaclass)
1961
{
1962
  int count;
1963
  ident_data_tuple *ref;
1964
  VEC (ident_data_tuple, gc) *list = metaclass  ? metaclass_super_refs
1965
                                                : class_super_refs;
1966
 
1967
  if (!list || !VEC_length (ident_data_tuple, list))
1968
    return;
1969
 
1970
  FOR_EACH_VEC_ELT (ident_data_tuple, list, count, ref)
1971
    {
1972
      tree expr = ref->ident;
1973
      tree decl = ref->data;
1974
      /* Interface with no implementation and yet one of its messages
1975
         has been used. Need to generate a full address-of tree for it
1976
         here.  */
1977
      if (TREE_CODE (expr) == IDENTIFIER_NODE)
1978
        {
1979
          const char * name = objc_build_internal_classname (expr, metaclass);
1980
          expr = create_extern_decl (objc_v2_class_template, name);
1981
          expr = convert (objc_class_type, build_fold_addr_expr (expr));
1982
        }
1983
      finish_var_decl (decl, expr);
1984
    }
1985
}
1986
 
1987
/* Add the global class meta-data declaration to the list which later
1988
   on ends up in the __class_list section.  */
1989
 
1990
static GTY(()) VEC(tree,gc) *class_list;
1991
 
1992
static void
1993
objc_v2_add_to_class_list (tree global_class_decl)
1994
{
1995
  if (!class_list)
1996
    class_list = VEC_alloc (tree, gc, imp_count?imp_count:1);
1997
  VEC_safe_push (tree, gc, class_list, global_class_decl);
1998
}
1999
 
2000
static GTY(()) VEC(tree,gc) *nonlazy_class_list;
2001
 
2002
/* Add the global class meta-data declaration to the list which later
2003
   on ends up in the __nonlazy_class section.  */
2004
 
2005
static void
2006
objc_v2_add_to_nonlazy_class_list (tree global_class_decl)
2007
{
2008
  if (!nonlazy_class_list)
2009
    nonlazy_class_list = VEC_alloc (tree, gc, imp_count?imp_count:1);
2010
  VEC_safe_push (tree, gc, nonlazy_class_list, global_class_decl);
2011
}
2012
 
2013
static GTY(()) VEC(tree,gc) *category_list;
2014
 
2015
/* Add the category meta-data declaration to the list which later on
2016
   ends up in the __nonlazy_category section.  */
2017
 
2018
static void
2019
objc_v2_add_to_category_list (tree decl)
2020
{
2021
  if (!category_list)
2022
    category_list = VEC_alloc (tree, gc, cat_count?cat_count:1);
2023
  VEC_safe_push (tree, gc, category_list, decl);
2024
}
2025
 
2026
static GTY(()) VEC(tree,gc) *nonlazy_category_list;
2027
 
2028
/* Add the category meta-data declaration to the list which later on
2029
   ends up in the __category_list section.  */
2030
 
2031
static void
2032
objc_v2_add_to_nonlazy_category_list (tree decl)
2033
{
2034
  if (!nonlazy_category_list)
2035
    nonlazy_category_list = VEC_alloc (tree, gc, cat_count?cat_count:1);
2036
  VEC_safe_push (tree, gc, nonlazy_category_list, decl);
2037
}
2038
 
2039
static bool
2040
has_load_impl (tree clsmeth)
2041
{
2042
  while (clsmeth)
2043
    {
2044
      tree id = METHOD_SEL_NAME (clsmeth);
2045
      if (IDENTIFIER_LENGTH (id) == 4
2046
          && strncmp (IDENTIFIER_POINTER (id), "load", 4) == 0)
2047
        return true;
2048
      clsmeth = DECL_CHAIN (clsmeth);
2049
    }
2050
 
2051
  return false;
2052
}
2053
 
2054
/* Build a __{class,category}_list section table containing address of
2055
   all @implemented {class,category} meta-data.  */
2056
 
2057
static void
2058
build_v2_address_table (VEC(tree,gc) *src, const char *nam, tree attr)
2059
{
2060
  int count=0;
2061
  tree type, decl, expr;
2062
  VEC(constructor_elt,gc) *initlist = NULL;
2063
 
2064
  if (!src || !VEC_length(tree,src))
2065
    return;
2066
 
2067
  FOR_EACH_VEC_ELT (tree, src, count, decl)
2068
    {
2069
#ifndef OBJCPLUS
2070
      tree purpose = build_int_cst (NULL_TREE, count);
2071
#else
2072
      tree purpose = NULL_TREE;
2073
#endif
2074
      expr = convert (objc_class_type, build_fold_addr_expr (decl));
2075
      CONSTRUCTOR_APPEND_ELT (initlist, purpose, expr);
2076
    }
2077
  gcc_assert (count > 0);
2078
  type = build_array_type (objc_class_type,
2079
                           build_index_type (build_int_cst (NULL_TREE, count - 1)));
2080
  decl = start_var_decl (type, nam);
2081
  /* The runtime wants this, even if it appears unused, so we must
2082
     force the output.  */
2083
  DECL_PRESERVE_P (decl) = 1;
2084
  expr = objc_build_constructor (type, initlist);
2085
  OBJCMETA (decl, objc_meta, attr);
2086
  finish_var_decl (decl, expr);
2087
}
2088
 
2089
/* Build decl = initializer; for each protocol referenced in
2090
   @protocol(MyProt) expression.  Refs as built in the entry section
2091
   above.  */
2092
 
2093
static void
2094
build_v2_protocol_list_translation_table (void)
2095
{
2096
  int count;
2097
  prot_list_entry *ref;
2098
 
2099
  if (!protrefs)
2100
    return;
2101
 
2102
  FOR_EACH_VEC_ELT (prot_list_entry, protrefs, count, ref)
2103
    {
2104
      char buf[BUFSIZE];
2105
      tree expr;
2106
      gcc_assert (TREE_CODE (ref->id) == PROTOCOL_INTERFACE_TYPE);
2107
      snprintf (buf, BUFSIZE, "_OBJC_Protocol_%s",
2108
                IDENTIFIER_POINTER (PROTOCOL_NAME (ref->id)));
2109
      expr = start_var_decl (objc_v2_protocol_template, buf);
2110
      expr = convert (objc_protocol_type, build_fold_addr_expr (expr));
2111
      finish_var_decl (ref->refdecl, expr);
2112
    }
2113
  /* TODO: Maybe we could explicitly delete the vec. now?  */
2114
}
2115
 
2116
static GTY (()) VEC (prot_list_entry, gc) * protlist;
2117
 
2118
/* Add the local protocol meta-data declaration to the list which
2119
   later on ends up in the __protocol_list section.  */
2120
 
2121
static void
2122
objc_add_to_protocol_list (tree protocol_interface_decl, tree protocol_decl)
2123
{
2124
  prot_list_entry e;
2125
  if (!protlist)
2126
    /* Arbitrary init count.  */
2127
    protlist = VEC_alloc (prot_list_entry, gc, 32);
2128
  e.id = protocol_interface_decl;
2129
  e.refdecl = protocol_decl;
2130
  VEC_safe_push (prot_list_entry, gc, protlist, &e);
2131
}
2132
 
2133
/* Build the __protocol_list section table containing address of all
2134
   generate protocol_t meta-data.  */
2135
 
2136
static void
2137
build_v2_protocol_list_address_table (void)
2138
{
2139
  int count;
2140
  prot_list_entry *ref;
2141
  if (!protlist || !VEC_length (prot_list_entry, protlist))
2142
    return;
2143
 
2144
  FOR_EACH_VEC_ELT (prot_list_entry, protlist, count, ref)
2145
    {
2146
      tree decl, expr;
2147
      char buf[BUFSIZE];
2148
      gcc_assert (ref->id && TREE_CODE (ref->id) == PROTOCOL_INTERFACE_TYPE);
2149
      snprintf (buf, BUFSIZE, "_OBJC_LabelProtocol_%s",
2150
                IDENTIFIER_POINTER (PROTOCOL_NAME (ref->id)));
2151
      decl = create_global_decl (objc_protocol_type, buf);
2152
      expr = convert (objc_protocol_type, build_fold_addr_expr (ref->refdecl));
2153
      OBJCMETA (decl, objc_meta, meta_label_protocollist);
2154
      finish_var_decl (decl, expr);
2155
    }
2156
 
2157
    /* TODO: delete the vec.  */
2158
    /* TODO: upgrade to the clang/llvm hidden version.  */
2159
}
2160
 
2161
/* This routine declares a variable to hold meta data for 'struct
2162
   protocol_list_t'.  */
2163
 
2164
static tree
2165
generate_v2_protocol_list (tree i_or_p, tree klass_ctxt)
2166
{
2167
  tree refs_decl, lproto, e, plist, ptempl_p_t;
2168
  int size = 0;
2169
  VEC(constructor_elt,gc) *initlist = NULL;
2170
  char buf[BUFSIZE];
2171
 
2172
  if (TREE_CODE (i_or_p) == CLASS_INTERFACE_TYPE
2173
      || TREE_CODE (i_or_p) == CATEGORY_INTERFACE_TYPE)
2174
    plist = CLASS_PROTOCOL_LIST (i_or_p);
2175
  else if (TREE_CODE (i_or_p) == PROTOCOL_INTERFACE_TYPE)
2176
    plist = PROTOCOL_LIST (i_or_p);
2177
  else
2178
    gcc_unreachable ();
2179
 
2180
  /* Compute size.  */
2181
  for (lproto = plist; lproto; lproto = TREE_CHAIN (lproto))
2182
    if (TREE_CODE (TREE_VALUE (lproto)) == PROTOCOL_INTERFACE_TYPE
2183
        && PROTOCOL_FORWARD_DECL (TREE_VALUE (lproto)))
2184
      size++;
2185
 
2186
  /* Build initializer.  */
2187
 
2188
  ptempl_p_t = build_pointer_type (objc_v2_protocol_template);
2189
  e = build_int_cst (ptempl_p_t, size);
2190
  CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, e);
2191
 
2192
  for (lproto = plist; lproto; lproto = TREE_CHAIN (lproto))
2193
    {
2194
      tree pval = TREE_VALUE (lproto);
2195
 
2196
      if (TREE_CODE (pval) == PROTOCOL_INTERFACE_TYPE
2197
          && PROTOCOL_FORWARD_DECL (pval))
2198
        {
2199
          tree fwref = PROTOCOL_FORWARD_DECL (pval);
2200
          location_t loc = DECL_SOURCE_LOCATION (fwref) ;
2201
          e = build_unary_op (loc, ADDR_EXPR, fwref, 0);
2202
          CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, e);
2203
        }
2204
    }
2205
 
2206
  /* static struct protocol_list_t *list[size]; */
2207
 
2208
  switch (TREE_CODE (i_or_p))
2209
    {
2210
    case PROTOCOL_INTERFACE_TYPE:
2211
      snprintf (buf, BUFSIZE, "_OBJC_ProtocolRefs_%s",
2212
                IDENTIFIER_POINTER (PROTOCOL_NAME (i_or_p)));
2213
      break;
2214
    case CLASS_INTERFACE_TYPE:
2215
      snprintf (buf, BUFSIZE, "_OBJC_ClassProtocols_%s",
2216
                IDENTIFIER_POINTER (CLASS_NAME (i_or_p)));
2217
      break;
2218
    case CATEGORY_INTERFACE_TYPE:
2219
      snprintf (buf, BUFSIZE, "_OBJC_CategoryProtocols_%s_%s",
2220
                IDENTIFIER_POINTER (CLASS_NAME (klass_ctxt)),
2221
                IDENTIFIER_POINTER (CLASS_SUPER_NAME (klass_ctxt)));
2222
      break;
2223
      default:
2224
        gcc_unreachable ();
2225
    }
2226
 
2227
  refs_decl = start_var_decl (build_sized_array_type (ptempl_p_t, size+1),
2228
                              buf);
2229
  /* ObjC2 puts all these in the base section.  */
2230
  OBJCMETA (refs_decl, objc_meta, meta_base);
2231
  DECL_PRESERVE_P (refs_decl) = 1;
2232
  finish_var_decl (refs_decl,
2233
                   objc_build_constructor (TREE_TYPE (refs_decl),initlist));
2234
  return refs_decl;
2235
}
2236
 
2237
/* This routine builds one 'struct method_t' initializer list. Note
2238
   that the old ABI is supposed to build 'struct objc_method' which
2239
   has 3 fields, but it does not build the initialization expression
2240
   for 'method_imp' which for protocols is NULL any way.  To be
2241
   consistant with declaration of 'struct method_t', in the new ABI we
2242
   set the method_t.imp to NULL.  */
2243
 
2244
static tree
2245
build_v2_descriptor_table_initializer (tree type, tree entries)
2246
{
2247
  VEC(constructor_elt,gc) *initlist = NULL;
2248
  do
2249
    {
2250
      VEC(constructor_elt,gc) *eltlist = NULL;
2251
      CONSTRUCTOR_APPEND_ELT (eltlist, NULL_TREE,
2252
                              build_selector (METHOD_SEL_NAME (entries)));
2253
      CONSTRUCTOR_APPEND_ELT (eltlist, NULL_TREE,
2254
                              add_objc_string (METHOD_ENCODING (entries),
2255
                                                meth_var_types));
2256
      CONSTRUCTOR_APPEND_ELT (eltlist, NULL_TREE, null_pointer_node);
2257
 
2258
      CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE,
2259
                              objc_build_constructor (type, eltlist));
2260
      entries = TREE_CHAIN (entries);
2261
    }
2262
  while (entries);
2263
 
2264
  return objc_build_constructor (build_array_type (type, 0), initlist);
2265
}
2266
 
2267
/* struct method_list_t
2268
  {
2269
     uint32_t entsize;
2270
     uint32_t method_count;
2271
     struct objc_method method_list[method_count];
2272
   }; */
2273
 
2274
static tree
2275
build_v2_method_list_template (tree list_type, int size)
2276
{
2277
  tree method_list_t_record;
2278
  tree array_type, decls, *chain = NULL;
2279
 
2280
  method_list_t_record = objc_start_struct (NULL_TREE);
2281
 
2282
  /* uint32_t const entsize; */
2283
  decls = add_field_decl (integer_type_node, "entsize", &chain);
2284
 
2285
  /* int method_count; */
2286
  add_field_decl (integer_type_node, "method_count", &chain);
2287
 
2288
  /* struct objc_method method_list[]; */
2289
  array_type = build_sized_array_type (list_type, size);
2290
  add_field_decl (array_type, "method_list", &chain);
2291
 
2292
  objc_finish_struct (method_list_t_record, decls);
2293
  return method_list_t_record;
2294
}
2295
 
2296
/* Note, as above that we are building to the objc_method_template
2297
   which has the *imp field.  ABI0/1 build with
2298
   objc_method_prototype_template which is missing this field.  */
2299
static tree
2300
generate_v2_meth_descriptor_table (tree chain, tree protocol,
2301
                                   const char *prefix, tree attr)
2302
{
2303
  tree method_list_template, initlist, decl, methods;
2304
  int size, entsize;
2305
  VEC(constructor_elt,gc) *v = NULL;
2306
  char buf[BUFSIZE];
2307
 
2308
  if (!chain || !prefix)
2309
    return NULL_TREE;
2310
 
2311
  methods = chain;
2312
  size = 0;
2313
  while (methods)
2314
    {
2315
      if (! METHOD_ENCODING (methods))
2316
        METHOD_ENCODING (methods) = encode_method_prototype (methods);
2317
      methods = TREE_CHAIN (methods);
2318
      size++;
2319
    }
2320
 
2321
  gcc_assert (size);
2322
  method_list_template = build_v2_method_list_template (objc_method_template,
2323
                                                        size);
2324
  snprintf (buf, BUFSIZE, "%s_%s", prefix,
2325
            IDENTIFIER_POINTER (PROTOCOL_NAME (protocol)));
2326
 
2327
  decl = start_var_decl (method_list_template, buf);
2328
 
2329
  entsize = TREE_INT_CST_LOW (TYPE_SIZE_UNIT (objc_method_template));
2330
  CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, build_int_cst (NULL_TREE, entsize));
2331
  CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, build_int_cst (NULL_TREE, size));
2332
  initlist =
2333
        build_v2_descriptor_table_initializer (objc_method_template,
2334
                                            chain);
2335
  CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, initlist);
2336
  /* Get into the right section.  */
2337
  OBJCMETA (decl, objc_meta, attr);
2338
  finish_var_decl (decl, objc_build_constructor (method_list_template, v));
2339
  return decl;
2340
}
2341
 
2342
/* This routine builds the initializer list to initialize the 'struct
2343
   _prop_t prop_list[]' field of 'struct _prop_list_t' meta-data.  */
2344
 
2345
static tree
2346
build_v2_property_table_initializer (tree type, tree context)
2347
{
2348
  tree x;
2349
  VEC(constructor_elt,gc) *inits = NULL;
2350
  if (TREE_CODE (context) == PROTOCOL_INTERFACE_TYPE)
2351
    x = CLASS_PROPERTY_DECL (context);
2352
  else
2353
    x = IMPL_PROPERTY_DECL (context);
2354
 
2355
  for (; x; x = TREE_CHAIN (x))
2356
    {
2357
      VEC(constructor_elt,gc) *elemlist = NULL;
2358
      /* NOTE! sections where property name/attribute go MUST change
2359
         later.  */
2360
      tree attribute, name_ident = PROPERTY_NAME (x);
2361
 
2362
      CONSTRUCTOR_APPEND_ELT (elemlist, NULL_TREE,
2363
                              add_objc_string (name_ident, prop_names_attr));
2364
 
2365
      attribute = objc_v2_encode_prop_attr (x);
2366
      CONSTRUCTOR_APPEND_ELT (elemlist, NULL_TREE,
2367
                              add_objc_string (attribute, prop_names_attr));
2368
 
2369
      CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE,
2370
                              objc_build_constructor (type, elemlist));
2371
    }
2372
 
2373
  return objc_build_constructor (build_array_type (type, 0),inits);
2374
}
2375
 
2376
/* This routine builds the following type:
2377
   struct _prop_list_t
2378
   {
2379
     uint32_t entsize;                  // sizeof (struct _prop_t)
2380
     uint32_t prop_count;
2381
     struct _prop_t prop_list [prop_count];
2382
   }
2383
*/
2384
 
2385
static tree
2386
build_v2_property_list_template (tree list_type, int size)
2387
{
2388
  tree property_list_t_record;
2389
  tree array_type, decls, *chain = NULL;
2390
 
2391
  /* anonymous.  */
2392
  property_list_t_record = objc_start_struct (NULL_TREE);
2393
 
2394
  /* uint32_t const entsize; */
2395
  decls = add_field_decl (integer_type_node, "entsize", &chain);
2396
 
2397
  /* int prop_count; */
2398
  add_field_decl (integer_type_node, "prop_count", &chain);
2399
 
2400
  /* struct _prop_t prop_list[]; */
2401
  array_type = build_sized_array_type (list_type, size);
2402
  add_field_decl (array_type, "prop_list", &chain);
2403
 
2404
  objc_finish_struct (property_list_t_record, decls);
2405
  return property_list_t_record;
2406
}
2407
 
2408
/* Top-level routine to generate property tables for each
2409
   implementation.  */
2410
 
2411
static tree
2412
generate_v2_property_table (tree context, tree klass_ctxt)
2413
{
2414
  tree x, decl, initlist, property_list_template;
2415
  bool is_proto = false;
2416
  VEC(constructor_elt,gc) *inits = NULL;
2417
  int init_val, size = 0;
2418
  char buf[BUFSIZE];
2419
 
2420
  if (context)
2421
    {
2422
      gcc_assert (TREE_CODE (context) == PROTOCOL_INTERFACE_TYPE);
2423
      x = CLASS_PROPERTY_DECL (context);
2424
      is_proto = true;
2425
    }
2426
  else
2427
    x = IMPL_PROPERTY_DECL (klass_ctxt);
2428
 
2429
  for (; x; x = TREE_CHAIN (x))
2430
    size++;
2431
 
2432
  if (size == 0)
2433
    return NULL_TREE;
2434
 
2435
  property_list_template =
2436
        build_v2_property_list_template (objc_v2_property_template,
2437
                                         size);
2438
 
2439
  initlist = build_v2_property_table_initializer (objc_v2_property_template,
2440
                                                  is_proto ? context
2441
                                                           : klass_ctxt);
2442
 
2443
  init_val = TREE_INT_CST_LOW (TYPE_SIZE_UNIT (objc_v2_property_template));
2444
  if (is_proto)
2445
    snprintf (buf, BUFSIZE, "_OBJC_ProtocolPropList_%s",
2446
              IDENTIFIER_POINTER (PROTOCOL_NAME (context)));
2447
  else
2448
    snprintf (buf, BUFSIZE, "_OBJC_ClassPropList_%s",
2449
              IDENTIFIER_POINTER (CLASS_NAME (klass_ctxt)));
2450
 
2451
  decl = start_var_decl (property_list_template, buf);
2452
 
2453
  CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE,
2454
                          build_int_cst (NULL_TREE, init_val));
2455
  CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE,
2456
                          build_int_cst (NULL_TREE, size));
2457
  CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, initlist);
2458
 
2459
  OBJCMETA (decl, objc_meta, meta_base);
2460
  finish_var_decl (decl, objc_build_constructor (TREE_TYPE (decl), inits));
2461
  return decl;
2462
}
2463
 
2464
static tree
2465
build_v2_protocol_initializer (tree type, tree protocol_name, tree protocol_list,
2466
                              tree inst_methods, tree class_methods,
2467
                              tree opt_ins_meth, tree opt_cls_meth,
2468
                              tree property_list)
2469
{
2470
  tree expr, ttyp;
2471
  location_t loc;
2472
  VEC(constructor_elt,gc) *inits = NULL;
2473
 
2474
  /* TODO: find a better representation of location from the inputs.  */
2475
  loc = UNKNOWN_LOCATION;
2476
 
2477
  /*  This is NULL for the new ABI.  */
2478
  CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE,
2479
                              convert (objc_object_type, null_pointer_node));
2480
 
2481
  CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, protocol_name);
2482
  CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, protocol_list);
2483
 
2484
  ttyp = objc_method_proto_list_ptr;
2485
  if (inst_methods)
2486
    expr = convert (ttyp, build_unary_op (loc, ADDR_EXPR, inst_methods, 0));
2487
  else
2488
    expr = convert (ttyp, null_pointer_node);
2489
  CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, expr);
2490
 
2491
  if (class_methods)
2492
    expr = convert (ttyp, build_unary_op (loc, ADDR_EXPR, class_methods, 0));
2493
  else
2494
    expr = convert (ttyp, null_pointer_node);
2495
  CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, expr);
2496
 
2497
  if (opt_ins_meth)
2498
    expr = convert (ttyp, build_unary_op (loc, ADDR_EXPR, opt_ins_meth, 0));
2499
  else
2500
    expr = convert (ttyp, null_pointer_node);
2501
  CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, expr);
2502
 
2503
  if (opt_cls_meth)
2504
    expr = convert (ttyp, build_unary_op (loc, ADDR_EXPR, opt_cls_meth, 0));
2505
  else
2506
    expr = convert (ttyp, null_pointer_node);
2507
  CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, expr);
2508
 
2509
  ttyp = objc_prop_list_ptr;
2510
  if (property_list)
2511
    expr = convert (ttyp, build_unary_op (loc, ADDR_EXPR, property_list, 0));
2512
  else
2513
    expr = convert (ttyp, null_pointer_node);
2514
  CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, expr);
2515
 
2516
  /* const uint32_t size;  = sizeof(struct protocol_t) */
2517
  expr = build_int_cst (integer_type_node,
2518
              TREE_INT_CST_LOW (TYPE_SIZE_UNIT (objc_v2_protocol_template)));
2519
  CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, expr);
2520
  /* const uint32_t flags; = 0 */
2521
  CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, integer_zero_node);
2522
 
2523
  return objc_build_constructor (type, inits);
2524
}
2525
 
2526
/* Main routine to build all meta data for all protocols used in a
2527
   translation unit.  */
2528
 
2529
static void
2530
generate_v2_protocols (void)
2531
{
2532
  tree p ;
2533
  bool some = false;
2534
 
2535
  if (!protocol_chain)
2536
    return ;
2537
 
2538
  /* If a protocol was directly referenced, pull in indirect
2539
     references.  */
2540
  for (p = protocol_chain; p; p = TREE_CHAIN (p))
2541
    if (PROTOCOL_FORWARD_DECL (p) && PROTOCOL_LIST (p))
2542
      generate_protocol_references (PROTOCOL_LIST (p));
2543
 
2544
  for (p = protocol_chain; p; p = TREE_CHAIN (p))
2545
    {
2546
      location_t loc;
2547
      tree inst_meth, class_meth, opt_inst_meth, opt_class_meth, props;
2548
      tree decl, initlist, protocol_name_expr, refs_decl, refs_expr;
2549
 
2550
      /* If protocol wasn't referenced, don't generate any code.  */
2551
      decl = PROTOCOL_FORWARD_DECL (p);
2552
 
2553
      if (!decl)
2554
        continue;
2555
 
2556
      loc = DECL_SOURCE_LOCATION (decl);
2557
      some = true;
2558
 
2559
      inst_meth =
2560
        generate_v2_meth_descriptor_table (PROTOCOL_NST_METHODS (p), p,
2561
                                           "_OBJC_ProtocolInstanceMethods",
2562
                                           meta_proto_nst_meth);
2563
 
2564
      class_meth =
2565
        generate_v2_meth_descriptor_table (PROTOCOL_CLS_METHODS (p), p,
2566
                                           "_OBJC_ProtocolClassMethods",
2567
                                           meta_proto_cls_meth);
2568
 
2569
      opt_inst_meth =
2570
        generate_v2_meth_descriptor_table (PROTOCOL_OPTIONAL_NST_METHODS (p), p,
2571
                                           "_OBJC_OptProtocolInstMethods",
2572
                                           meta_proto_nst_meth);
2573
 
2574
      opt_class_meth =
2575
        generate_v2_meth_descriptor_table (PROTOCOL_OPTIONAL_CLS_METHODS (p), p,
2576
                                           "_OBJC_OptProtocolClassMethods",
2577
                                           meta_proto_cls_meth);
2578
 
2579
      if (PROTOCOL_LIST (p))
2580
        refs_decl = generate_v2_protocol_list (p, NULL_TREE);
2581
      else
2582
        refs_decl = 0;
2583
 
2584
      /* static struct objc_protocol _OBJC_Protocol_<mumble>; */
2585
      protocol_name_expr = add_objc_string (PROTOCOL_NAME (p), class_names);
2586
 
2587
      if (refs_decl)
2588
        refs_expr = convert (build_pointer_type (objc_v2_protocol_template),
2589
                             build_unary_op (loc, ADDR_EXPR, refs_decl, 0));
2590
      else
2591
        refs_expr = build_int_cst (NULL_TREE, 0);
2592
 
2593
      props = generate_v2_property_table (p, NULL_TREE);
2594
 
2595
      initlist = build_v2_protocol_initializer (TREE_TYPE (decl),
2596
                                                protocol_name_expr, refs_expr,
2597
                                                inst_meth, class_meth,
2598
                                                opt_inst_meth, opt_class_meth,
2599
                                                props);
2600
      finish_var_decl (decl, initlist);
2601
      objc_add_to_protocol_list (p, decl);
2602
    }
2603
 
2604
  if (some)
2605
    {
2606
      /* Make sure we get the Protocol class linked in - reference
2607
         it...  */
2608
      p = objc_v2_get_class_reference (get_identifier (PROTOCOL_OBJECT_CLASS_NAME));
2609
      /* ... but since we don't specifically use the reference...  we
2610
         need to force it.  */
2611
      DECL_PRESERVE_P (p) = 1;
2612
    }
2613
}
2614
 
2615
static tree
2616
generate_v2_dispatch_table (tree chain, const char *name, tree attr)
2617
{
2618
  tree decl, method_list_template, initlist;
2619
  VEC(constructor_elt,gc) *v = NULL;
2620
  int size, init_val;
2621
 
2622
  if (!chain || !name || !(size = list_length (chain)))
2623
    return NULL_TREE;
2624
 
2625
  method_list_template
2626
        = build_v2_method_list_template (objc_method_template, size);
2627
  initlist
2628
        = build_dispatch_table_initializer (objc_method_template, chain);
2629
 
2630
  decl = start_var_decl  (method_list_template, name);
2631
 
2632
  init_val = TREE_INT_CST_LOW (TYPE_SIZE_UNIT (objc_method_template));
2633
  CONSTRUCTOR_APPEND_ELT (v, NULL_TREE,
2634
                          build_int_cst (integer_type_node, init_val));
2635
  CONSTRUCTOR_APPEND_ELT (v, NULL_TREE,
2636
                          build_int_cst (integer_type_node, size));
2637
  CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, initlist);
2638
 
2639
  OBJCMETA (decl, objc_meta, attr);
2640
  finish_var_decl (decl,
2641
                   objc_build_constructor (TREE_TYPE (decl), v));
2642
  return decl;
2643
}
2644
 
2645
/* Init a category.  */
2646
static tree
2647
build_v2_category_initializer (tree type, tree cat_name, tree class_name,
2648
                                tree inst_methods, tree class_methods,
2649
                                tree protocol_list, tree property_list,
2650
                                location_t loc)
2651
{
2652
  tree expr, ltyp;
2653
  VEC(constructor_elt,gc) *v = NULL;
2654
 
2655
  CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, cat_name);
2656
  CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, class_name);
2657
 
2658
  ltyp = objc_method_list_ptr;
2659
  if (inst_methods)
2660
    expr = convert (ltyp, build_unary_op (loc, ADDR_EXPR, inst_methods, 0));
2661
  else
2662
    expr = convert (ltyp, null_pointer_node);
2663
  CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
2664
 
2665
  if (class_methods)
2666
    expr = convert (ltyp, build_unary_op (loc, ADDR_EXPR, class_methods, 0));
2667
  else
2668
    expr = convert (ltyp, null_pointer_node);
2669
  CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
2670
 
2671
  /* protocol_list = */
2672
  ltyp = build_pointer_type (objc_v2_protocol_template);
2673
  if (protocol_list)
2674
    expr = convert (ltyp, build_unary_op (loc, ADDR_EXPR, protocol_list, 0));
2675
  else
2676
    expr = convert (ltyp, null_pointer_node);
2677
  CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
2678
 
2679
  ltyp = objc_prop_list_ptr;
2680
  if (property_list)
2681
    expr = convert (ltyp, build_unary_op (loc, ADDR_EXPR, property_list, 0));
2682
  else
2683
    expr = convert (ltyp, null_pointer_node);
2684
  CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
2685
 
2686
  return objc_build_constructor (type, v);
2687
}
2688
 
2689
/* static struct category_t _OBJC_CATEGORY_$_<name> = { ... }; */
2690
 
2691
static void
2692
generate_v2_category (struct imp_entry *impent)
2693
{
2694
  tree initlist, cat_name_expr, class_name_expr;
2695
  tree protocol_decl, category, props, t;
2696
  tree inst_methods = NULL_TREE, class_methods = NULL_TREE;
2697
  tree cat = impent->imp_context;
2698
  tree cat_decl = impent->class_decl;
2699
  location_t loc;
2700
  char buf[BUFSIZE];
2701
 
2702
  loc = DECL_SOURCE_LOCATION (cat_decl);
2703
 
2704
  /* ??? not sure this is really necessary, the following references should
2705
     force appropriate linkage linkage...
2706
     -- but ... ensure a reference to the class...  */
2707
  t = objc_v2_get_class_reference (CLASS_NAME (cat));
2708
  /* ... which we ignore so force it out.. */
2709
  DECL_PRESERVE_P (t) = 1;
2710
 
2711
  snprintf (buf, BUFSIZE, "OBJC_CLASS_$_%s", IDENTIFIER_POINTER (CLASS_NAME (cat)));
2712
  class_name_expr = create_extern_decl (objc_v2_class_template, buf);
2713
  class_name_expr = build_fold_addr_expr (class_name_expr);
2714
 
2715
  cat_name_expr = add_objc_string (CLASS_SUPER_NAME (cat), class_names);
2716
  category = lookup_category (impent->imp_template, CLASS_SUPER_NAME (cat));
2717
 
2718
  if (category && CLASS_PROTOCOL_LIST (category))
2719
    {
2720
      generate_protocol_references (CLASS_PROTOCOL_LIST (category));
2721
      protocol_decl = generate_v2_protocol_list (category, cat);
2722
    }
2723
  else
2724
    protocol_decl = NULL_TREE;
2725
 
2726
/* decl = update_var_decl(impent->class_decl); */
2727
 
2728
  props = generate_v2_property_table (NULL_TREE, cat);
2729
 
2730
  if (CLASS_NST_METHODS (cat))
2731
    {
2732
      snprintf (buf, BUFSIZE, "_OBJC_CategoryInstanceMethods_%s_%s",
2733
                IDENTIFIER_POINTER (CLASS_NAME (cat)),
2734
                IDENTIFIER_POINTER (CLASS_SUPER_NAME (cat)));
2735
      inst_methods = generate_v2_dispatch_table (CLASS_NST_METHODS (cat), buf,
2736
                                                 meta_cati_meth);
2737
    }
2738
 
2739
  if (CLASS_CLS_METHODS (cat))
2740
    {
2741
      snprintf (buf, BUFSIZE, "_OBJC_CategoryClassMethods_%s_%s",
2742
                IDENTIFIER_POINTER (CLASS_NAME (cat)),
2743
                IDENTIFIER_POINTER (CLASS_SUPER_NAME (cat)));
2744
      class_methods = generate_v2_dispatch_table (CLASS_CLS_METHODS (cat), buf,
2745
                                                  meta_catc_meth);
2746
    }
2747
 
2748
  initlist = build_v2_category_initializer (TREE_TYPE (cat_decl),
2749
                                            cat_name_expr, class_name_expr,
2750
                                            inst_methods, class_methods,
2751
                                            protocol_decl, props, loc);
2752
 
2753
  finish_var_decl (cat_decl, initlist);
2754
  impent->class_decl = cat_decl;
2755
 
2756
  /* Add to list of pointers in __category_list section.  */
2757
  objc_v2_add_to_category_list (cat_decl);
2758
  if (has_load_impl (CLASS_CLS_METHODS (impent->imp_context)))
2759
    objc_v2_add_to_nonlazy_category_list (cat_decl);
2760
}
2761
 
2762
/* This routine declares a variable to hold the offset for ivar
2763
   FIELD_DECL.  Variable name is .objc_ivar.ClassName.IvarName.  */
2764
 
2765
typedef struct GTY(()) ivarref_entry
2766
{
2767
  tree decl;
2768
  tree offset;
2769
} ivarref_entry;
2770
DEF_VEC_O(ivarref_entry);
2771
DEF_VEC_ALLOC_O(ivarref_entry, gc);
2772
 
2773
static GTY (()) VEC (ivarref_entry, gc) * ivar_offset_refs;
2774
 
2775
static tree
2776
ivar_offset_ref (tree class_name, tree field_decl)
2777
{
2778
  tree decl, field_decl_id;
2779
  ivarref_entry e;
2780
  bool global_var;
2781
  char buf[512];
2782
 
2783
  create_ivar_offset_name (buf, class_name, field_decl);
2784
  field_decl_id = get_identifier (buf);
2785
 
2786
  if (ivar_offset_refs)
2787
    {
2788
      int count;
2789
      ivarref_entry *ref;
2790
      FOR_EACH_VEC_ELT (ivarref_entry, ivar_offset_refs, count, ref)
2791
        if (DECL_NAME (ref->decl) == field_decl_id)
2792
          return ref->decl;
2793
    }
2794
  else
2795
    /* Somewhat arbitrary initial provision.  */
2796
    ivar_offset_refs = VEC_alloc (ivarref_entry, gc, 32);
2797
 
2798
  /* We come here if we don't find a match or at the start.  */
2799
  global_var = (TREE_PUBLIC (field_decl) || TREE_PROTECTED (field_decl));
2800
  if (global_var)
2801
    decl = create_global_decl (TREE_TYPE (size_zero_node), buf);
2802
  else
2803
    decl = create_hidden_decl (TREE_TYPE (size_zero_node), buf);
2804
 
2805
  /* Make sure it ends up in an ObjC section.  */
2806
  OBJCMETA (decl, objc_meta, meta_base);
2807
 
2808
  e.decl = decl;
2809
  e.offset = byte_position (field_decl);
2810
  VEC_safe_push (ivarref_entry, gc, ivar_offset_refs, &e);
2811
  return decl;
2812
}
2813
 
2814
/* This routine builds initializer-list needed to initialize 'struct
2815
   ivar_t list[count] of 'struct ivar_list_t' meta data. TYPE is
2816
   'struct ivar_t' and FIELD_DECL is list of ivars for the target
2817
   class.  */
2818
 
2819
static tree
2820
build_v2_ivar_list_initializer (tree class_name, tree type, tree field_decl)
2821
{
2822
  VEC(constructor_elt,gc) *inits = NULL;
2823
 
2824
  do
2825
    {
2826
      VEC(constructor_elt,gc) *ivar = NULL;
2827
      int val;
2828
      tree id;
2829
 
2830
      /* Unnamed bitfields are ignored.  */
2831
      if (!DECL_NAME (field_decl))
2832
        {
2833
          field_decl = DECL_CHAIN (field_decl);
2834
          continue;
2835
        }
2836
 
2837
      /* Set offset.  */
2838
      CONSTRUCTOR_APPEND_ELT (ivar, NULL_TREE,
2839
                              build_unary_op (input_location,
2840
                                              ADDR_EXPR,
2841
                                              ivar_offset_ref (class_name,
2842
                                                               field_decl), 0));
2843
 
2844
      /* Set name.  */
2845
      CONSTRUCTOR_APPEND_ELT (ivar, NULL_TREE,
2846
                              add_objc_string (DECL_NAME (field_decl),
2847
                                                meth_var_names));
2848
 
2849
      /* Set type.  */
2850
      id = add_objc_string (encode_field_decl (field_decl),
2851
                            meth_var_types);
2852
      CONSTRUCTOR_APPEND_ELT (ivar, NULL_TREE, id);
2853
 
2854
      /* Set alignment.  */
2855
      val = DECL_ALIGN_UNIT (field_decl);
2856
      val = exact_log2 (val);
2857
      CONSTRUCTOR_APPEND_ELT (ivar, NULL_TREE,
2858
                              build_int_cst (integer_type_node, val));
2859
 
2860
      /* Set size.  */
2861
      val = TREE_INT_CST_LOW (DECL_SIZE_UNIT (field_decl));
2862
      CONSTRUCTOR_APPEND_ELT (ivar, NULL_TREE,
2863
                              build_int_cst (integer_type_node, val));
2864
 
2865
      CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE,
2866
                              objc_build_constructor (type, ivar));
2867
 
2868
      do
2869
        field_decl = DECL_CHAIN (field_decl);
2870
      while (field_decl && TREE_CODE (field_decl) != FIELD_DECL);
2871
    }
2872
  while (field_decl);
2873
 
2874
  return objc_build_constructor (build_array_type (type, 0), inits);
2875
}
2876
 
2877
/*
2878
  struct ivar_list_t
2879
  {
2880
    uint32 entsize;
2881
    uint32 count;
2882
    struct iver_t list[count];
2883
  };
2884
*/
2885
 
2886
static tree
2887
build_v2_ivar_list_t_template (tree list_type, int size)
2888
{
2889
  tree objc_ivar_list_record;
2890
  tree decls, *chain = NULL;
2891
 
2892
  /* Anonymous.  */
2893
  objc_ivar_list_record = objc_start_struct (NULL_TREE);
2894
 
2895
  /* uint32 entsize; */
2896
  decls = add_field_decl (integer_type_node, "entsize", &chain);
2897
 
2898
  /* uint32 count; */
2899
  add_field_decl (integer_type_node, "count", &chain);
2900
 
2901
  /* struct objc_ivar ivar_list[]; */
2902
  add_field_decl (build_sized_array_type (list_type, size),
2903
                          "list", &chain);
2904
 
2905
  objc_finish_struct (objc_ivar_list_record, decls);
2906
  return objc_ivar_list_record;
2907
}
2908
 
2909
/* This routine declares a static variable of type 'struct
2910
   ivar_list_t' and initializes it.  chain is the source of the data,
2911
   name is the name for the var.  attr is the meta-data section tag
2912
   attribute.  templ is the implementation template for the class.  */
2913
 
2914
static tree
2915
generate_v2_ivars_list (tree chain, const char *name, tree attr, tree templ)
2916
{
2917
  tree decl, initlist, ivar_list_template;
2918
  VEC(constructor_elt,gc) *inits = NULL;
2919
  int size, ivar_t_size;
2920
 
2921
  if (!chain || !name || !(size = ivar_list_length (chain)))
2922
    return NULL_TREE;
2923
 
2924
  generating_instance_variables = 1;
2925
  ivar_list_template = build_v2_ivar_list_t_template (objc_v2_ivar_template,
2926
                                                      size);
2927
 
2928
  initlist = build_v2_ivar_list_initializer (CLASS_NAME (templ),
2929
                                             objc_v2_ivar_template, chain);
2930
  ivar_t_size = TREE_INT_CST_LOW  (TYPE_SIZE_UNIT (objc_v2_ivar_template));
2931
 
2932
  decl = start_var_decl (ivar_list_template, name);
2933
  CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE,
2934
                          build_int_cst (integer_type_node, ivar_t_size));
2935
  CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE,
2936
                          build_int_cst (integer_type_node, size));
2937
  CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, initlist);
2938
  OBJCMETA (decl, objc_meta, attr);
2939
  finish_var_decl (decl, objc_build_constructor (TREE_TYPE (decl), inits));
2940
  generating_instance_variables = 0;
2941
  return decl;
2942
}
2943
 
2944
/* Routine to build initializer list to initialize objects of type
2945
   struct class_t; */
2946
 
2947
static tree
2948
build_v2_class_t_initializer (tree type, tree isa, tree superclass,
2949
                              tree ro, tree cache, tree vtable)
2950
{
2951
  VEC(constructor_elt,gc) *initlist = NULL;
2952
 
2953
  /* isa */
2954
  CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, isa);
2955
 
2956
  /* superclass */
2957
  CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, superclass);
2958
 
2959
  /* cache */
2960
  if (cache)
2961
    CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, cache);
2962
  else
2963
    CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, null_pointer_node);
2964
 
2965
  /* vtable */
2966
  if (vtable)
2967
    CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, vtable);
2968
  else
2969
    CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, null_pointer_node);
2970
 
2971
  /* ro */
2972
  CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, ro);
2973
 
2974
  return objc_build_constructor (type, initlist);
2975
}
2976
 
2977
/* Routine to build object of struct class_ro_t { ... }; */
2978
 
2979
static tree
2980
build_v2_class_ro_t_initializer (tree type, tree name,
2981
                               unsigned int flags, unsigned int instanceStart,
2982
                               unsigned int instanceSize,
2983
                               tree ivarLayout,
2984
                               tree baseMethods, tree baseProtocols,
2985
                               tree ivars, tree property_list)
2986
{
2987
  tree expr, unsigned_char_star, ltyp;
2988
  location_t loc;
2989
  VEC(constructor_elt,gc) *initlist = NULL;
2990
 
2991
  /* TODO: fish out the real location from somewhere.  */
2992
  loc = UNKNOWN_LOCATION;
2993
 
2994
  /* flags */
2995
  CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE,
2996
                          build_int_cst (integer_type_node, flags));
2997
 
2998
  /* instanceStart */
2999
  CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE,
3000
                          build_int_cst (integer_type_node, instanceStart));
3001
 
3002
  /* instanceSize */
3003
  CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE,
3004
                          build_int_cst (integer_type_node, instanceSize));
3005
 
3006
  /* This ABI is currently only used on m64 NeXT.  We always
3007
     explicitly declare the alignment padding.  */
3008
  /* reserved, pads alignment.  */
3009
  CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE,
3010
                            build_int_cst (integer_type_node, 0));
3011
 
3012
  /* ivarLayout */
3013
  unsigned_char_star = build_pointer_type (unsigned_char_type_node);
3014
  if (ivarLayout)
3015
    expr = ivarLayout;
3016
  else
3017
    expr = convert (unsigned_char_star, null_pointer_node);
3018
  CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, expr);
3019
 
3020
  /* name */
3021
  CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, default_conversion (name));
3022
 
3023
  /* baseMethods */
3024
  ltyp = objc_method_list_ptr;
3025
  if (baseMethods)
3026
    expr = convert (ltyp, build_unary_op (loc, ADDR_EXPR, baseMethods, 0));
3027
  else
3028
    expr = convert (ltyp, null_pointer_node);
3029
  CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, expr);
3030
 
3031
  /* baseProtocols */
3032
  ltyp = build_pointer_type (xref_tag (RECORD_TYPE,
3033
                                       get_identifier (UTAG_V2_PROTOCOL_LIST)));
3034
  if (baseProtocols)
3035
    expr = convert (ltyp, build_unary_op (loc, ADDR_EXPR, baseProtocols, 0));
3036
  else
3037
    expr = convert (ltyp, null_pointer_node);
3038
  CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, expr);
3039
 
3040
  /* ivars */
3041
  ltyp = objc_v2_ivar_list_ptr;
3042
  if (ivars)
3043
    expr = convert (ltyp, build_unary_op (loc, ADDR_EXPR, ivars, 0));
3044
  else
3045
    expr = convert (ltyp, null_pointer_node);
3046
  CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, expr);
3047
 
3048
  /* TODO: We don't yet have the weak/strong stuff...  */
3049
  /* weakIvarLayout */
3050
  CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE,
3051
                          convert (unsigned_char_star, null_pointer_node));
3052
 
3053
  /* property list */
3054
  ltyp = objc_prop_list_ptr;
3055
  if (property_list)
3056
    expr = convert (ltyp, build_unary_op (loc, ADDR_EXPR, property_list, 0));
3057
  else
3058
    expr = convert (ltyp, null_pointer_node);
3059
  CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, expr);
3060
  return objc_build_constructor (type, initlist);
3061
}
3062
 
3063
static GTY (()) VEC (ident_data_tuple, gc) * ehtype_list;
3064
 
3065
/* Record a name as needing a catcher.  */
3066
static void
3067
objc_v2_add_to_ehtype_list (tree name)
3068
{
3069
  ident_data_tuple e;
3070
  if (ehtype_list)
3071
    {
3072
      int count = 0;
3073
      ident_data_tuple *ref;
3074
 
3075
      FOR_EACH_VEC_ELT (ident_data_tuple, ehtype_list, count, ref)
3076
        if (ref->ident == name)
3077
          return; /* Already entered.  */
3078
     }
3079
  else
3080
    /* Arbitrary initial count.  */
3081
    ehtype_list = VEC_alloc (ident_data_tuple, gc, 8);
3082
 
3083
  /* Not found, or new list.  */
3084
  e.ident = name;
3085
  e.data = NULL_TREE;
3086
  VEC_safe_push (ident_data_tuple, gc, ehtype_list, &e);
3087
}
3088
 
3089
static void
3090
generate_v2_class_structs (struct imp_entry *impent)
3091
{
3092
  tree decl, name_expr, initlist, protocol_decl, metaclass_decl, class_decl;
3093
  tree field, firstIvar, chain;
3094
  tree class_superclass_expr, metaclass_superclass_expr, props;
3095
  /* TODO: figure out how to compute this.  */
3096
  tree ivarLayout = NULL_TREE;
3097
  tree my_super_id = NULL_TREE, root_expr = NULL_TREE;
3098
  tree inst_methods = NULL_TREE, class_methods = NULL_TREE;
3099
  tree inst_ivars = NULL_TREE, class_ivars = NULL_TREE;
3100
  location_t loc;
3101
  char buf[BUFSIZE];
3102
  unsigned int instanceStart, instanceSize;
3103
  unsigned int flags = 0x01; /* RO_META */
3104
  int cls_flags = impent->has_cxx_cdtors ? OBJC2_CLS_HAS_CXX_STRUCTORS
3105
                                         : 0 ;
3106
 
3107
  class_decl = impent->class_decl;
3108
  metaclass_decl = impent->meta_decl;
3109
  loc = DECL_SOURCE_LOCATION (class_decl);
3110
 
3111
  DECL_EXTERNAL (class_decl) = DECL_EXTERNAL (metaclass_decl) = 0;
3112
  TREE_PUBLIC (class_decl) = TREE_PUBLIC (metaclass_decl) = 1;
3113
#ifdef OBJCPLUS
3114
  gcc_assert (!CP_DECL_CONTEXT (class_decl) || CP_DECL_CONTEXT (class_decl) == global_namespace);
3115
  gcc_assert (!CP_DECL_CONTEXT (metaclass_decl) || CP_DECL_CONTEXT (metaclass_decl) == global_namespace);
3116
#endif
3117
 
3118
  /* Generation of data for meta class.  */
3119
  my_super_id = CLASS_SUPER_NAME (impent->imp_template);
3120
  if (my_super_id)
3121
    {
3122
      /* Compute reference to root's name.  For a meta class, "isa" is
3123
         a reference to the root class name. */
3124
      tree my_root_id = my_super_id;
3125
      tree my_root_int, interface;
3126
      do
3127
        {
3128
          my_root_int = lookup_interface (my_root_id);
3129
 
3130
          if (my_root_int && CLASS_SUPER_NAME (my_root_int))
3131
            my_root_id = CLASS_SUPER_NAME (my_root_int);
3132
          else
3133
            break;
3134
        }
3135
      while (1);
3136
 
3137
      /* {extern} struct class_t OBJC_METACLASS_$_<my_root_int>
3138
         create extern if not already declared.  */
3139
      snprintf (buf, BUFSIZE, "OBJC_METACLASS_$_%s",
3140
                IDENTIFIER_POINTER (CLASS_NAME (my_root_int)));
3141
      root_expr = create_extern_decl (objc_v2_class_template, buf);
3142
      root_expr = build_fold_addr_expr (root_expr);
3143
 
3144
      /* Install class `isa' and `super' pointers at runtime.  */
3145
      interface = lookup_interface (my_super_id);
3146
      gcc_assert (interface);
3147
      /* Similarly, for OBJC_CLASS_$_<interface>...  */
3148
      snprintf (buf, BUFSIZE, "OBJC_CLASS_$_%s",
3149
                IDENTIFIER_POINTER (CLASS_NAME (interface)));
3150
      class_superclass_expr = create_extern_decl (objc_v2_class_template, buf);
3151
      class_superclass_expr = build_fold_addr_expr (class_superclass_expr);
3152
      /* ... and for OBJC_METACLASS_$_<interface>.  */
3153
      snprintf (buf, BUFSIZE, "OBJC_METACLASS_$_%s",
3154
                IDENTIFIER_POINTER (CLASS_NAME (interface)));
3155
      metaclass_superclass_expr = create_extern_decl (objc_v2_class_template, buf);
3156
      metaclass_superclass_expr = build_fold_addr_expr (metaclass_superclass_expr);
3157
    }
3158
  else
3159
    {
3160
      /* Root class.  */
3161
      root_expr = build_unary_op (loc, ADDR_EXPR, metaclass_decl, 0);
3162
      metaclass_superclass_expr = build_unary_op (loc, ADDR_EXPR, class_decl, 0);
3163
      class_superclass_expr = build_int_cst (NULL_TREE, 0);
3164
      flags |= 0x02; /* RO_ROOT: it is also a root meta class.  */
3165
    }
3166
 
3167
  if (CLASS_PROTOCOL_LIST (impent->imp_template))
3168
    {
3169
      generate_protocol_references (CLASS_PROTOCOL_LIST (impent->imp_template));
3170
      protocol_decl = generate_v2_protocol_list (impent->imp_template,
3171
                                                 impent->imp_context);
3172
    }
3173
  else
3174
    protocol_decl = 0;
3175
 
3176
  name_expr = add_objc_string (CLASS_NAME (impent->imp_template),
3177
                               class_names);
3178
 
3179
  if (CLASS_CLS_METHODS (impent->imp_context))
3180
    {
3181
      snprintf (buf, BUFSIZE, "_OBJC_ClassMethods_%s",
3182
                IDENTIFIER_POINTER (CLASS_NAME (impent->imp_context)));
3183
      class_methods =
3184
        generate_v2_dispatch_table (CLASS_CLS_METHODS (impent->imp_context),
3185
                                    buf, meta_clac_meth);
3186
    }
3187
 
3188
  instanceStart = TREE_INT_CST_LOW (TYPE_SIZE_UNIT (objc_v2_class_template));
3189
 
3190
  /* Currently there are no class ivars and generation of class
3191
     variables for the root of the inheritance has been removed.  It
3192
     causes multiple defines if there are two root classes in the
3193
     link, because each will define its own identically-named offset
3194
     variable.  */
3195
 
3196
  class_ivars = NULL_TREE;
3197
  /* TODO: Add total size of class variables when implemented. */
3198
  instanceSize = TREE_INT_CST_LOW (TYPE_SIZE_UNIT (objc_v2_class_template));
3199
 
3200
  /* So now build the META CLASS structs.  */
3201
  /* static struct class_ro_t  _OBJC_METACLASS_Foo = { ... }; */
3202
 
3203
  decl = start_var_decl (objc_v2_class_ro_template,
3204
                         newabi_append_ro (IDENTIFIER_POINTER
3205
                                                (DECL_NAME (metaclass_decl))));
3206
 
3207
  /* TODO: ivarLayout needs t be built.  */
3208
  initlist =
3209
        build_v2_class_ro_t_initializer (TREE_TYPE (decl), name_expr,
3210
                                        (flags | cls_flags), instanceStart,
3211
                                        instanceSize, ivarLayout,
3212
                                        class_methods, protocol_decl,
3213
                                        class_ivars, NULL_TREE);
3214
  /* The ROs sit in the default const section.  */
3215
  OBJCMETA (decl, objc_meta, meta_base);
3216
  finish_var_decl (decl, initlist);
3217
 
3218
  /* static struct class_t _OBJC_METACLASS_Foo = { ... }; */
3219
  initlist =
3220
        build_v2_class_t_initializer (TREE_TYPE (metaclass_decl),
3221
                                      root_expr,
3222
                                      metaclass_superclass_expr,
3223
                                      build_fold_addr_expr (decl),
3224
                                      build_fold_addr_expr (UOBJC_V2_CACHE_decl),
3225
                                      build_fold_addr_expr (UOBJC_V2_VTABLE_decl));
3226
  /* The class section attributes are set when they are created.  */
3227
  finish_var_decl (metaclass_decl, initlist);
3228
  impent->meta_decl = metaclass_decl;
3229
 
3230
  /* So now build the CLASS structs.  */
3231
 
3232
  flags = 0x0;          /* ... */
3233
  if (!my_super_id)
3234
    flags |= 0x02;      /* RO_ROOT: this is a root class */
3235
 
3236
  if (DECL_VISIBILITY (class_decl) == VISIBILITY_HIDDEN)
3237
    flags |= 0x10;      /* RO_HIDDEN, OBJC2_CLS_HIDDEN; */
3238
 
3239
  if (objc2_objc_exception_attr (impent->imp_template))
3240
    flags |= 0x20;      /* RO_EXCEPTION */
3241
 
3242
  if (CLASS_NST_METHODS (impent->imp_context))
3243
    {
3244
      snprintf (buf, BUFSIZE, "_OBJC_InstanceMethods_%s",
3245
                IDENTIFIER_POINTER (CLASS_NAME (impent->imp_context)));
3246
      inst_methods =
3247
        generate_v2_dispatch_table (CLASS_NST_METHODS (impent->imp_context),
3248
                                    buf, meta_clai_meth);
3249
    }
3250
 
3251
  /* Sort out the ivars before we try to compute the class sizes.  */
3252
  if ((chain = CLASS_IVARS (impent->imp_template)))
3253
    {
3254
      snprintf (buf, BUFSIZE, "_OBJC_InstanceIvars_%s",
3255
                IDENTIFIER_POINTER (CLASS_NAME (impent->imp_context)));
3256
      inst_ivars = generate_v2_ivars_list (chain, buf, meta_clai_vars,
3257
                                           impent->imp_template);
3258
    }
3259
 
3260
  /* Compute instanceStart.  */
3261
  gcc_assert (CLASS_STATIC_TEMPLATE (impent->imp_template));
3262
  field = TYPE_FIELDS (CLASS_STATIC_TEMPLATE (impent->imp_template));
3263
  if (my_super_id && field && TREE_CHAIN (field))
3264
    field = TREE_CHAIN (field);
3265
 
3266
  firstIvar = field;
3267
 
3268
  while (firstIvar && TREE_CODE (firstIvar) != FIELD_DECL)
3269
    firstIvar = TREE_CHAIN (firstIvar);
3270
 
3271
  gcc_assert (inst_ivars? (firstIvar != NULL_TREE): true);
3272
 
3273
  /* Compute instanceSize.  */
3274
  while (field && TREE_CHAIN (field)
3275
         && TREE_CODE (TREE_CHAIN (field)) == FIELD_DECL)
3276
    field = TREE_CHAIN (field);
3277
 
3278
  if (field && TREE_CODE (field) == FIELD_DECL)
3279
    instanceSize = int_byte_position (field) * BITS_PER_UNIT
3280
                   + tree_low_cst (DECL_SIZE (field), 0);
3281
  else
3282
    instanceSize = 0;
3283
  instanceSize /= BITS_PER_UNIT;
3284
 
3285
  props = generate_v2_property_table (NULL_TREE, impent->imp_context);
3286
 
3287
  /* If the class has no ivars, instanceStart should be set to the
3288
     superclass's instanceSize.  */
3289
  instanceStart =
3290
        (inst_ivars != NULL_TREE) ? (unsigned) int_byte_position (firstIvar)
3291
                                  : instanceSize;
3292
 
3293
  /* static struct class_ro_t  _OBJC_CLASS_Foo = { ... }; */
3294
  decl = start_var_decl (objc_v2_class_ro_template,
3295
                         newabi_append_ro (IDENTIFIER_POINTER
3296
                                                (DECL_NAME (class_decl))));
3297
 
3298
  initlist =
3299
        build_v2_class_ro_t_initializer (TREE_TYPE (decl), name_expr,
3300
                                         (flags | cls_flags), instanceStart,
3301
                                         instanceSize, ivarLayout,
3302
                                         inst_methods, protocol_decl,
3303
                                         inst_ivars, props);
3304
  /* The ROs sit in the default const section.  */
3305
  OBJCMETA (decl, objc_meta, meta_base);
3306
  finish_var_decl (decl, initlist);
3307
 
3308
  /* static struct class_t _OBJC_CLASS_Foo = { ... }; */
3309
  initlist = build_v2_class_t_initializer (TREE_TYPE (class_decl),
3310
                                        build_fold_addr_expr (metaclass_decl),
3311
                                        class_superclass_expr,
3312
                                        build_fold_addr_expr (decl),
3313
                                        build_fold_addr_expr (UOBJC_V2_CACHE_decl),
3314
                                        build_fold_addr_expr (UOBJC_V2_VTABLE_decl));
3315
 
3316
  /* The class section attributes are set when they are created.  */
3317
  finish_var_decl (class_decl, initlist);
3318
  impent->class_decl = class_decl;
3319
 
3320
  objc_v2_add_to_class_list (class_decl);
3321
  if (has_load_impl (CLASS_CLS_METHODS (impent->imp_context)))
3322
    objc_v2_add_to_nonlazy_class_list (class_decl);
3323
 
3324
  if (flags & 0x20) /* RO_EXCEPTION */
3325
    objc_v2_add_to_ehtype_list (CLASS_NAME (impent->imp_template));
3326
}
3327
 
3328
/* This routine outputs the (ivar_reference_offset, offset)
3329
   tuples.  */
3330
 
3331
static void
3332
build_v2_ivar_offset_ref_table (void)
3333
{
3334
  int count;
3335
  ivarref_entry *ref;
3336
 
3337
  if (!ivar_offset_refs || !VEC_length (ivarref_entry, ivar_offset_refs))
3338
    return;
3339
 
3340
  FOR_EACH_VEC_ELT (ivarref_entry, ivar_offset_refs, count, ref)
3341
    finish_var_decl (ref->decl, ref->offset);
3342
}
3343
 
3344
/* static int _OBJC_IMAGE_INFO[2] = { 0, 16 | flags }; */
3345
 
3346
static void
3347
generate_v2_objc_image_info (void)
3348
{
3349
  tree decl, array_type;
3350
  VEC(constructor_elt,gc) *v = NULL;
3351
  int flags =
3352
        ((flag_replace_objc_classes && imp_count ? 1 : 0)
3353
          | (flag_objc_gc ? 2 : 0));
3354
 
3355
  flags |= 16;
3356
 
3357
  array_type  = build_sized_array_type (integer_type_node, 2);
3358
 
3359
  decl = start_var_decl (array_type, "_OBJC_ImageInfo");
3360
 
3361
  CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, integer_zero_node);
3362
  CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, build_int_cst (integer_type_node, flags));
3363
  /* The Runtime wants this.  */
3364
  DECL_PRESERVE_P (decl) = 1;
3365
  OBJCMETA (decl, objc_meta, meta_info);
3366
  finish_var_decl (decl, objc_build_constructor (TREE_TYPE (decl), v));
3367
}
3368
 
3369
static void
3370
objc_generate_v2_next_metadata (void)
3371
{
3372
  struct imp_entry *impent;
3373
 
3374
  /* FIXME: Make sure that we generate no metadata if there is nothing
3375
     to put into it.  */
3376
 
3377
  gcc_assert (!objc_static_instances); /* Not for NeXT */
3378
 
3379
  build_metadata_templates ();
3380
 
3381
  for (impent = imp_list; impent; impent = impent->next)
3382
    {
3383
      /* If -gen-decls is present, Dump the @interface of each class.
3384
         TODO: Dump the classes in the order they were found, rather
3385
         than in reverse order as we are doing now.  */
3386
      if (flag_gen_declaration)
3387
        dump_interface (gen_declaration_file, impent->imp_context);
3388
 
3389
      /* all of the following reference the string pool...  */
3390
      if (TREE_CODE (impent->imp_context) == CLASS_IMPLEMENTATION_TYPE)
3391
        generate_v2_class_structs (impent);
3392
      else
3393
        generate_v2_category (impent);
3394
    }
3395
 
3396
  build_next_selector_translation_table ();
3397
  build_v2_message_ref_translation_table ();
3398
 
3399
  /* This will add "Protocol" to the class refs.  */
3400
  generate_v2_protocols ();
3401
 
3402
  build_v2_classrefs_table ();
3403
  build_v2_super_classrefs_table (/*metaclass= */false);
3404
  build_v2_super_classrefs_table (/*metaclass= */true);
3405
 
3406
  build_v2_ivar_offset_ref_table ();
3407
 
3408
  build_v2_protocol_list_translation_table ();
3409
  build_v2_protocol_list_address_table ();
3410
 
3411
  build_v2_address_table (class_list, "_OBJC_ClassList$",
3412
                          meta_label_classlist);
3413
  build_v2_address_table (category_list, "_OBJC_CategoryList$",
3414
                          meta_label_categorylist);
3415
  build_v2_address_table (nonlazy_class_list, "_OBJC_NonLazyClassList$",
3416
                          meta_label_nonlazy_classlist);
3417
  build_v2_address_table (nonlazy_category_list, "_OBJC_NonLazyCategoryList$",
3418
                          meta_label_nonlazy_categorylist);
3419
 
3420
  /* This conveys information on GC usage and zero-link.  */
3421
  generate_v2_objc_image_info ();
3422
 
3423
  /* Generate catch objects for eh, if any are needed.  */
3424
  build_v2_eh_catch_objects ();
3425
 
3426
  /* Emit the string table last.  */
3427
  generate_strings ();
3428
}
3429
 
3430
/* NOTE --- Output NeXT V2 Exceptions --- */
3431
 
3432
static GTY(()) tree objc_v2_ehtype_template;
3433
static GTY(()) tree next_v2_ehvtable_decl;
3434
static GTY(()) tree next_v2_EHTYPE_id_decl;
3435
 
3436
static void
3437
build_v2_ehtype_template (void)
3438
{
3439
  tree decls, *chain = NULL;
3440
  objc_v2_ehtype_template = objc_start_struct (get_identifier (UTAG_V2_EH_TYPE));
3441
 
3442
  /* void *_objc_ehtype_vtable; */
3443
  decls = add_field_decl (ptr_type_node, "_objc_ehtype_vtable_ptr", &chain);
3444
 
3445
  /* const char *className; */
3446
  add_field_decl (string_type_node, "className", &chain);
3447
 
3448
  /* struct class_t *const cls; */
3449
  add_field_decl (build_pointer_type (objc_v2_class_template), "cls", &chain);
3450
 
3451
  objc_finish_struct (objc_v2_ehtype_template, decls);
3452
}
3453
 
3454
/* Template for the Objective-C family typeinfo type for ABI=2.  This
3455
   starts off the same as the gxx/cxx eh typeinfo.
3456
 
3457
   struct _objc_ehtype_t
3458
   {
3459
     void *_objc_ehtype_vtable_ptr;     - as per c++
3460
     const char *className;             - as per c++
3461
     struct class_t *const cls;
3462
   }
3463
*/
3464
 
3465
/* This routine builds initializer list for object of type struct _objc_ehtype_t.
3466
*/
3467
 
3468
static tree
3469
objc2_build_ehtype_initializer (tree name, tree cls)
3470
{
3471
  VEC(constructor_elt,gc) *initlist = NULL;
3472
  tree addr, offs;
3473
 
3474
  /* This is done the same way as c++, missing the two first entries
3475
     in the parent vtable.  NOTE: there is a fix-me in the Apple/NeXT
3476
     runtime source about this so, perhaps, this will change at some
3477
     point.  */
3478
  /* _objc_ehtype_vtable + 2*sizeof(void*)  */
3479
  if (!next_v2_ehvtable_decl)
3480
    {
3481
      next_v2_ehvtable_decl =
3482
                        start_var_decl (ptr_type_node, TAG_NEXT_EHVTABLE_NAME);
3483
      TREE_STATIC (next_v2_ehvtable_decl) = 0;
3484
      DECL_EXTERNAL (next_v2_ehvtable_decl) = 1;
3485
      TREE_PUBLIC (next_v2_ehvtable_decl) = 1;
3486
    }
3487
  addr = build_fold_addr_expr_with_type (next_v2_ehvtable_decl, ptr_type_node);
3488
  offs = size_int (2 * int_cst_value (TYPE_SIZE_UNIT (ptr_type_node)));
3489
  addr = fold_build_pointer_plus (addr, offs);
3490
 
3491
  CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, addr);
3492
 
3493
  /* className */
3494
  CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, name);
3495
 
3496
  /* cls */
3497
  CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, cls);
3498
 
3499
  return objc_build_constructor (objc_v2_ehtype_template, initlist);
3500
}
3501
 
3502
static tree
3503
build_ehtype (tree name, const char *eh_name, bool weak)
3504
{
3505
  tree name_expr, class_name_expr, ehtype_decl, inits;
3506
 
3507
  name_expr = add_objc_string (name, class_names);
3508
  /* Extern ref. for the class. ???  Maybe we can look this up
3509
     somewhere.  */
3510
  class_name_expr =
3511
        create_extern_decl (objc_v2_class_template,
3512
                            objc_build_internal_classname (name, false));
3513
  class_name_expr = build_fold_addr_expr (class_name_expr);
3514
  ehtype_decl = create_global_decl (objc_v2_ehtype_template, eh_name);
3515
  if (weak)
3516
    DECL_WEAK (ehtype_decl) = 1;
3517
  inits = objc2_build_ehtype_initializer (name_expr, class_name_expr);
3518
  OBJCMETA (ehtype_decl, objc_meta, meta_ehtype);
3519
  finish_var_decl (ehtype_decl, inits);
3520
  return ehtype_decl;
3521
}
3522
 
3523
/* This routine returns TRUE if CLS or any of its super classes has
3524
   __attribute__ ((objc_exception)).  */
3525
 
3526
static bool
3527
objc2_objc_exception_attr (tree cls)
3528
{
3529
  while (cls)
3530
    {
3531
      if (CLASS_HAS_EXCEPTION_ATTR (cls))
3532
        return true;
3533
      cls = lookup_interface (CLASS_SUPER_NAME (cls));
3534
    }
3535
 
3536
  return false;
3537
}
3538
 
3539
static bool
3540
is_implemented (tree name)
3541
{
3542
  struct imp_entry *t;
3543
  for (t = imp_list; t; t = t->next)
3544
    if (TREE_CODE (t->imp_context) == CLASS_IMPLEMENTATION_TYPE
3545
        && CLASS_NAME (t->imp_template) == name)
3546
      return true;
3547
 
3548
  return false;
3549
}
3550
 
3551
/* We will build catch objects:
3552
     for any type  implemented here.
3553
     for any type used in a catch that has no exception attribute.  */
3554
static void build_v2_eh_catch_objects (void)
3555
{
3556
  int count=0;
3557
  ident_data_tuple *ref;
3558
 
3559
  if (!ehtype_list || !VEC_length (ident_data_tuple, ehtype_list))
3560
    return;
3561
 
3562
  FOR_EACH_VEC_ELT (ident_data_tuple, ehtype_list, count, ref)
3563
    {
3564
      char buf[BUFSIZE];
3565
      bool impl = is_implemented (ref->ident);
3566
      bool excpt = objc2_objc_exception_attr (lookup_interface (ref->ident));
3567
      snprintf (buf, BUFSIZE, "OBJC_EHTYPE_$_%s", IDENTIFIER_POINTER (ref->ident));
3568
      if (!impl && excpt)
3569
        /* The User says this class has a catcher already.  */
3570
        ref->data = create_extern_decl (objc_v2_ehtype_template, buf);
3571
      else
3572
        /* Create a catcher, weak if it wasn't marked.  */
3573
        ref->data = build_ehtype (ref->ident, buf, !excpt);
3574
    }
3575
}
3576
 
3577
static tree
3578
lookup_ehtype_ref (tree id)
3579
{
3580
  int count=0;
3581
  ident_data_tuple *ref;
3582
 
3583
  if (!ehtype_list || !VEC_length (ident_data_tuple, ehtype_list))
3584
    return NULL_TREE;
3585
 
3586
  FOR_EACH_VEC_ELT (ident_data_tuple, ehtype_list, count, ref)
3587
    if (ref->ident == id)
3588
      return ref->data;
3589
  return NULL_TREE;
3590
}
3591
 
3592
/* This hook, called via lang_eh_runtime_type, generates a runtime
3593
   object which is either the address of the 'OBJC_EHTYPE_$_class'
3594
   object or address of external OBJC_EHTYPE_id object.  */
3595
static tree
3596
next_runtime_02_eh_type (tree type)
3597
{
3598
  tree t;
3599
 
3600
  if (type == error_mark_node
3601
      /*|| errorcount || sorrycount*/)
3602
    goto err_mark_in;
3603
 
3604
  if (POINTER_TYPE_P (type) && objc_is_object_id (TREE_TYPE (type)))
3605
    {
3606
      if (!next_v2_EHTYPE_id_decl)
3607
        {
3608
          /* This is provided by the Apple/NeXT libobjc.dylib so we
3609
             need only to reference it.  */
3610
          next_v2_EHTYPE_id_decl =
3611
                start_var_decl (objc_v2_ehtype_template, "OBJC_EHTYPE_id");
3612
          DECL_EXTERNAL (next_v2_EHTYPE_id_decl) = 1;
3613
          TREE_PUBLIC (next_v2_EHTYPE_id_decl) = 1;
3614
          TREE_STATIC (next_v2_EHTYPE_id_decl) = 0;
3615
        }
3616
      return build_fold_addr_expr (next_v2_EHTYPE_id_decl);
3617
    }
3618
 
3619
  if (!POINTER_TYPE_P (type) || !TYPED_OBJECT (TREE_TYPE (type)))
3620
    {
3621
#ifdef OBJCPLUS
3622
      /* This routine is also called for c++'s catch clause; in which
3623
         case, we use c++'s typeinfo decl.  */
3624
      return build_eh_type_type (type);
3625
#else
3626
      error ("non-objective-c type '%T' cannot be caught", type);
3627
      goto err_mark_in;
3628
#endif
3629
    }
3630
  else
3631
    t = OBJC_TYPE_NAME (TREE_TYPE (type));
3632
 
3633
  /* We have to build a reference to the OBJC_EHTYPE_<Class>.  */
3634
  t = lookup_ehtype_ref (t);
3635
  if (!t)
3636
    goto err_mark_in;
3637
 
3638
  return build_fold_addr_expr (t);
3639
 
3640
err_mark_in:
3641
  return error_mark_node;
3642
}
3643
 
3644
static GTY(()) tree objc_eh_personality_decl;
3645
 
3646
static tree
3647
objc_eh_personality (void)
3648
{
3649
  if (!objc_eh_personality_decl)
3650
    objc_eh_personality_decl = build_personality_function  ("objc");
3651
  return objc_eh_personality_decl;
3652
}
3653
 
3654
/* NOTE --- interfaces --- */
3655
 
3656
static tree
3657
build_throw_stmt (location_t loc, tree throw_expr, bool rethrown)
3658
{
3659
  tree t;
3660
  if (rethrown)
3661
    /* We have a separate re-throw entry.  */
3662
    t = build_function_call_vec (loc, objc_rethrow_exception_decl, NULL, NULL);
3663
  else
3664
    {
3665
      /* Throw like the others...  */
3666
      VEC(tree, gc) *parms = VEC_alloc (tree, gc, 1);
3667
      VEC_quick_push (tree, parms, throw_expr);
3668
      t = build_function_call_vec (loc, objc_exception_throw_decl, parms, NULL);
3669
      VEC_free (tree, gc, parms);
3670
    }
3671
  return add_stmt (t);
3672
}
3673
 
3674
/* Build __builtin_eh_pointer.  */
3675
 
3676
static tree
3677
objc_build_exc_ptr (struct objc_try_context **x ATTRIBUTE_UNUSED)
3678
{
3679
  tree t;
3680
  t = builtin_decl_explicit (BUILT_IN_EH_POINTER);
3681
  t = build_call_expr (t, 1, integer_zero_node);
3682
  return fold_convert (objc_object_type, t);
3683
}
3684
 
3685
static tree begin_catch (struct objc_try_context **cur_try_context, tree type,
3686
                         tree decl, tree compound, bool ellipsis ATTRIBUTE_UNUSED)
3687
{
3688
  tree t;
3689
 
3690
  /* Record the data for the catch in the try context so that we can
3691
     finalize it later.  Ellipsis is signalled by a NULL entry.  */
3692
  if (ellipsis)
3693
    t = build_stmt (input_location, CATCH_EXPR, NULL_TREE, compound);
3694
  else
3695
    t = build_stmt (input_location, CATCH_EXPR, type, compound);
3696
  (*cur_try_context)->current_catch = t;
3697
 
3698
  /* Initialize the decl from the EXC_PTR_EXPR we get from the runtime.  */
3699
  t = objc_build_exc_ptr (cur_try_context);
3700
  t = convert (TREE_TYPE (decl), t);
3701
  /* FIXME: location.  */
3702
  if (type && type != error_mark_node)
3703
    {
3704
      t = build1(NOP_EXPR, ptr_type_node, t);
3705
      t = build_function_call (input_location, objc2_begin_catch_decl,
3706
                              tree_cons (NULL_TREE, t, NULL_TREE));
3707
 
3708
      /* We might want to build a catch object for this (if it's not
3709
         id).  */
3710
      if (POINTER_TYPE_P (type)
3711
          && !objc_is_object_id (TREE_TYPE (type))
3712
          && TYPED_OBJECT (TREE_TYPE (type)))
3713
        objc_v2_add_to_ehtype_list (OBJC_TYPE_NAME (TREE_TYPE (type)));
3714
    }
3715
  return build2 (MODIFY_EXPR, void_type_node, decl, t);
3716
}
3717
 
3718
/* try { catch-body } finally { objc_end_catch (); } */
3719
static void
3720
finish_catch (struct objc_try_context **cur_try_context, tree curr_catch)
3721
{
3722
  struct objc_try_context *ct;
3723
  tree try_exp, func, *l, t ;
3724
  location_t loc = (*cur_try_context)->try_locus;
3725
 
3726
  if (!curr_catch || curr_catch == error_mark_node)
3727
    return;
3728
 
3729
  t = CATCH_BODY (curr_catch);
3730
  if (TREE_CODE (t) == BIND_EXPR)
3731
    {
3732
      /* Usual case of @catch (objc-expr).  */
3733
      objc_begin_try_stmt (loc, BIND_EXPR_BODY (t));
3734
      BIND_EXPR_BODY (t) = NULL_TREE;
3735
      l = &BIND_EXPR_BODY (t);
3736
    }
3737
  else
3738
    {
3739
      /* NULL entry, meaning @catch (...).  */
3740
      objc_begin_try_stmt (loc, t);
3741
      CATCH_BODY (curr_catch) = NULL_TREE;
3742
      l = &CATCH_BODY (curr_catch);
3743
    }
3744
 
3745
  /* Pick up the new context we made in begin_try above...  */
3746
  ct = *cur_try_context;
3747
  func = build_function_call_vec (loc, objc2_end_catch_decl, NULL, NULL);
3748
  append_to_statement_list (func, &ct->finally_body);
3749
  try_exp = build_stmt (loc, TRY_FINALLY_EXPR, ct->try_body, ct->finally_body);
3750
  *cur_try_context = ct->outer;
3751
  free (ct);
3752
  append_to_statement_list (try_exp, l);
3753
  append_to_statement_list (curr_catch, &((*cur_try_context)->catch_list));
3754
}
3755
 
3756
static tree
3757
finish_try_stmt (struct objc_try_context **cur_try_context)
3758
{
3759
  struct objc_try_context *c = *cur_try_context;
3760
  tree stmt = c->try_body;
3761
  if (c->catch_list)
3762
    stmt = build_stmt (c->try_locus, TRY_CATCH_EXPR, stmt, c->catch_list);
3763
  if (c->finally_body)
3764
    stmt = build_stmt (c->try_locus, TRY_FINALLY_EXPR, stmt, c->finally_body);
3765
  return stmt;
3766
}
3767
 
3768
#include "gt-objc-objc-next-runtime-abi-02.h"

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.