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

Subversion Repositories openrisc

[/] [openrisc/] [tags/] [gnu-dev/] [fsf-gcc-snapshot-1-mar-12/] [or1k-gcc/] [gcc/] [objc/] [objc-next-runtime-abi-01.c] - Blame information for rev 847

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

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

powered by: WebSVN 2.1.0

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