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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [gcc/] [objc/] [objc-gnu-runtime-abi-01.c] - Blame information for rev 742

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

Line No. Rev Author Line
1 717 jeremybenn
/* GNU Runtime ABI version 8
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
#include "config.h"
22
#include "system.h"
23
#include "coretypes.h"
24
#include "tree.h"
25
 
26
#ifdef OBJCPLUS
27
#include "cp-tree.h"
28
#else
29
#include "c-tree.h"
30
#include "c-lang.h"
31
#endif
32
 
33
#include "langhooks.h"
34
#include "c-family/c-objc.h"
35
#include "objc-act.h"
36
 
37
/* When building Objective-C++, we are not linking against the C front-end
38
   and so need to replicate the C tree-construction functions in some way.  */
39
#ifdef OBJCPLUS
40
#define OBJCP_REMAP_FUNCTIONS
41
#include "objcp-decl.h"
42
#endif  /* OBJCPLUS */
43
 
44
#include "toplev.h"
45
#include "ggc.h"
46
#include "tree-iterator.h"
47
 
48
#include "objc-runtime-hooks.h"
49
#include "objc-runtime-shared-support.h"
50
#include "objc-encoding.h"
51
 
52
/* GNU runtime private definitions.  */
53
#define DEF_CONSTANT_STRING_CLASS_NAME "NXConstantString"
54
 
55
#define TAG_GETCLASS            "objc_get_class"
56
#define TAG_GETMETACLASS        "objc_get_meta_class"
57
 
58
#define TAG_MSGSEND             "objc_msg_lookup"
59
#define TAG_MSGSENDSUPER        "objc_msg_lookup_super"
60
 
61
/* GNU-specific tags.  */
62
 
63
#define TAG_EXECCLASS           "__objc_exec_class"
64
#define TAG_GNUINIT             "__objc_gnu_init"
65
 
66
/* The version identifies which language generation and runtime
67
   the module (file) was compiled for, and is recorded in the
68
   module descriptor.  */
69
#define OBJC_VERSION            8
70
 
71
#define PROTOCOL_VERSION        2
72
 
73
/* This macro provides a method of removing ambiguity between runtimes
74
   when LTO is in use on targets supporting multiple runtimes.
75
 
76
   For example, at present, any target that includes an implementation of
77
   the NeXT runtime needs to place Objective-C meta-data into specific
78
   named sections.  This should _not_ be done for the GNU runtime, and the
79
   folowing macro is used to attach Objective-C private attributes that may
80
   be used to identify the runtime for which the meta-data are intended.  */
81
 
82
#define OBJCMETA(DECL,VERS,KIND)                                        \
83
  if (VERS)                                                             \
84
    DECL_ATTRIBUTES (DECL) = build_tree_list ((VERS), (KIND));
85
 
86
static void gnu_runtime_01_initialize (void);
87
 
88
static void build_selector_template (void);
89
 
90
static tree gnu_runtime_abi_01_super_superclassfield_id (void);
91
 
92
static tree gnu_runtime_abi_01_class_decl (tree);
93
static tree gnu_runtime_abi_01_metaclass_decl (tree);
94
static tree gnu_runtime_abi_01_category_decl (tree);
95
static tree gnu_runtime_abi_01_protocol_decl (tree);
96
static tree gnu_runtime_abi_01_string_decl (tree, const char *, string_section);
97
 
98
static tree gnu_runtime_abi_01_get_class_reference (tree);
99
static tree gnu_runtime_abi_01_build_typed_selector_reference (location_t, tree,
100
                                                                tree);
101
static tree gnu_runtime_abi_01_get_protocol_reference (location_t, tree);
102
static tree gnu_runtime_abi_01_build_ivar_ref (location_t, tree, tree);
103
static tree gnu_runtime_abi_01_get_class_super_ref (location_t, struct imp_entry *, bool);
104
static tree gnu_runtime_abi_01_get_category_super_ref (location_t, struct imp_entry *, bool);
105
 
106
static tree gnu_runtime_abi_01_receiver_is_class_object (tree);
107
static void gnu_runtime_abi_01_get_arg_type_list_base (VEC(tree,gc) **, tree,
108
                                                       int, int);
109
static tree gnu_runtime_abi_01_build_objc_method_call (location_t, tree, tree,
110
                                                        tree, tree, tree, int);
111
 
112
static bool gnu_runtime_abi_01_setup_const_string_class_decl (void);
113
static tree gnu_runtime_abi_01_build_const_string_constructor (location_t, tree,int);
114
 
115
static void objc_generate_v1_gnu_metadata (void);
116
 
117
static tree objc_eh_runtime_type (tree type);
118
static tree objc_eh_personality (void);
119
static tree objc_build_exc_ptr (struct objc_try_context **);
120
static tree build_throw_stmt (location_t, tree, bool);
121
static tree begin_catch (struct objc_try_context **, tree, tree, tree, bool);
122
static void finish_catch (struct objc_try_context **, tree);
123
static tree finish_try_stmt (struct objc_try_context **);
124
 
125
bool
126
objc_gnu_runtime_abi_01_init (objc_runtime_hooks *rthooks)
127
{
128
  /* GNU runtime does not need the compiler to change code in order to do GC. */
129
  if (flag_objc_gc)
130
    {
131
      warning_at (0, 0, "%<-fobjc-gc%> is ignored for %<-fgnu-runtime%>");
132
      flag_objc_gc = 0;
133
    }
134
 
135
  /* Although I guess we could, we don't currently support SJLJ exceptions for the
136
     GNU runtime.  */
137
  if (flag_objc_sjlj_exceptions)
138
    {
139
      inform (UNKNOWN_LOCATION, "%<-fobjc-sjlj-exceptions%> is ignored for %<-fgnu-runtime%>");
140
      flag_objc_sjlj_exceptions = 0;
141
    }
142
 
143
  /* TODO: Complain if -fobjc-abi-version=N was used.  */
144
 
145
  /* TODO: Complain if -fobj-nilcheck was used.  */
146
 
147
  rthooks->initialize = gnu_runtime_01_initialize;
148
  rthooks->default_constant_string_class_name = DEF_CONSTANT_STRING_CLASS_NAME;
149
  rthooks->tag_getclass = TAG_GETCLASS;
150
  rthooks->super_superclassfield_ident = gnu_runtime_abi_01_super_superclassfield_id;
151
 
152
  rthooks->class_decl = gnu_runtime_abi_01_class_decl;
153
  rthooks->metaclass_decl = gnu_runtime_abi_01_metaclass_decl;
154
  rthooks->category_decl = gnu_runtime_abi_01_category_decl;
155
  rthooks->protocol_decl = gnu_runtime_abi_01_protocol_decl;
156
  rthooks->string_decl = gnu_runtime_abi_01_string_decl;
157
 
158
  rthooks->get_class_reference = gnu_runtime_abi_01_get_class_reference;
159
  rthooks->build_selector_reference = gnu_runtime_abi_01_build_typed_selector_reference;
160
  rthooks->get_protocol_reference = gnu_runtime_abi_01_get_protocol_reference;
161
  rthooks->build_ivar_reference = gnu_runtime_abi_01_build_ivar_ref;
162
  rthooks->get_class_super_ref = gnu_runtime_abi_01_get_class_super_ref;
163
  rthooks->get_category_super_ref = gnu_runtime_abi_01_get_category_super_ref;
164
 
165
  rthooks->receiver_is_class_object = gnu_runtime_abi_01_receiver_is_class_object;
166
  rthooks->get_arg_type_list_base = gnu_runtime_abi_01_get_arg_type_list_base;
167
  rthooks->build_objc_method_call = gnu_runtime_abi_01_build_objc_method_call;
168
 
169
  rthooks->setup_const_string_class_decl =
170
                                gnu_runtime_abi_01_setup_const_string_class_decl;
171
  rthooks->build_const_string_constructor =
172
                                gnu_runtime_abi_01_build_const_string_constructor;
173
 
174
  rthooks->build_throw_stmt = build_throw_stmt;
175
  rthooks->build_exc_ptr = objc_build_exc_ptr;
176
  rthooks->begin_catch = begin_catch;
177
  rthooks->finish_catch = finish_catch;
178
  rthooks->finish_try_stmt = finish_try_stmt;
179
 
180
  rthooks->generate_metadata = objc_generate_v1_gnu_metadata;
181
  return true;
182
}
183
 
184
static void build_selector_table_decl (void);
185
static void build_class_template (void);
186
static void build_category_template (void);
187
static void build_protocol_template (void);
188
 
189
static GTY(()) tree objc_meta;
190
static GTY(()) tree meta_base;
191
 
192
static void gnu_runtime_01_initialize (void)
193
{
194
  tree type, ftype, IMP_type;
195
 
196
  /* We do not need to mark GNU ObjC metadata for different sections,
197
     however, we do need to make sure that it is not mistaken for NeXT
198
     metadata.  */
199
  objc_meta = get_identifier ("OBJC1METG");
200
  meta_base = get_identifier ("NONE");
201
 
202
  /* Declare type of selector-objects that represent an operation name.  */
203
  /* `const struct objc_selector *' */
204
  type = xref_tag (RECORD_TYPE, get_identifier (TAG_SELECTOR));
205
  type = build_qualified_type (type, TYPE_QUAL_CONST);
206
  objc_selector_type = build_pointer_type (type);
207
 
208
  /* typedef id (*IMP)(id, SEL, ...); */
209
  ftype = build_varargs_function_type_list (objc_object_type,
210
                                            objc_object_type,
211
                                            objc_selector_type,
212
                                            NULL_TREE);
213
 
214
  IMP_type = build_pointer_type (ftype);
215
 
216
  build_class_template ();
217
  build_super_template ();
218
  build_protocol_template ();
219
  build_category_template ();
220
 
221
  /* GNU runtime messenger entry points.  */
222
  /* TREE_NOTHROW is cleared for the message-sending functions,
223
     because the function that gets called can throw in Obj-C++, or
224
     could itself call something that can throw even in Obj-C.  */
225
 
226
  /* IMP objc_msg_lookup (id, SEL); */
227
  type = build_function_type_list (IMP_type,
228
                                   objc_object_type,
229
                                   objc_selector_type,
230
                                   NULL_TREE);
231
 
232
  umsg_decl = add_builtin_function (TAG_MSGSEND,
233
                                    type, 0, NOT_BUILT_IN,
234
                                    NULL, NULL_TREE);
235
  TREE_NOTHROW (umsg_decl) = 0;
236
 
237
  /* IMP objc_msg_lookup_super (struct objc_super *, SEL); */
238
  type = build_function_type_list (IMP_type,
239
                                   objc_super_type,
240
                                   objc_selector_type,
241
                                   NULL_TREE);
242
 
243
  umsg_super_decl = add_builtin_function (TAG_MSGSENDSUPER,
244
                                          type, 0, NOT_BUILT_IN,
245
                                          NULL, NULL_TREE);
246
  TREE_NOTHROW (umsg_super_decl) = 0;
247
 
248
  /* The following GNU runtime entry point is called to initialize
249
         each module:
250
 
251
         __objc_exec_class (void *); */
252
  type = build_function_type_list (void_type_node,
253
                                   ptr_type_node,
254
                                   NULL_TREE);
255
 
256
  execclass_decl = add_builtin_function (TAG_EXECCLASS,
257
                                         type, 0, NOT_BUILT_IN,
258
                                         NULL, NULL_TREE);
259
 
260
  type = build_function_type_list (objc_object_type,
261
                                   const_string_type_node,
262
                                   NULL_TREE);
263
 
264
  /* id objc_getClass (const char *); */
265
  objc_get_class_decl
266
    = add_builtin_function (TAG_GETCLASS, type, 0, NOT_BUILT_IN,
267
                            NULL, NULL_TREE);
268
 
269
  /* id objc_getMetaClass (const char *); */
270
  objc_get_meta_class_decl = add_builtin_function (TAG_GETMETACLASS, type,
271
                                                   0, NOT_BUILT_IN, NULL,
272
                                                   NULL_TREE);
273
 
274
  /* static SEL _OBJC_SELECTOR_TABLE[]; */
275
  build_selector_table_decl ();
276
 
277
  /* Stuff for properties.
278
     The codegen relies on this being NULL for GNU.  */
279
  objc_copyStruct_decl = NULL_TREE;
280
 
281
  /* This is the type of all of the following functions
282
     bjc_getPropertyStruct() and objc_setPropertyStruct().  */
283
  type = build_function_type_list (void_type_node,
284
                                   ptr_type_node,
285
                                   const_ptr_type_node,
286
                                   ptrdiff_type_node,
287
                                   boolean_type_node,
288
                                   boolean_type_node,
289
                                   NULL_TREE);
290
 
291
  /* Declare the following function:
292
         void
293
         objc_getPropertyStruct (void *destination, const void *source,
294
                                 ptrdiff_t size, BOOL is_atomic, BOOL has_strong);  */
295
  objc_getPropertyStruct_decl = add_builtin_function ("objc_getPropertyStruct",
296
                                                          type, 0, NOT_BUILT_IN,
297
                                                          NULL, NULL_TREE);
298
  TREE_NOTHROW (objc_getPropertyStruct_decl) = 0;
299
  /* Declare the following function:
300
         void
301
         objc_setPropertyStruct (void *destination, const void *source,
302
                                 ptrdiff_t size, BOOL is_atomic, BOOL has_strong);  */
303
  objc_setPropertyStruct_decl = add_builtin_function ("objc_setPropertyStruct",
304
                                                          type, 0, NOT_BUILT_IN,
305
                                                          NULL, NULL_TREE);
306
  TREE_NOTHROW (objc_setPropertyStruct_decl) = 0;
307
 
308
  using_eh_for_cleanups ();
309
  lang_hooks.eh_runtime_type = objc_eh_runtime_type;
310
  lang_hooks.eh_personality = objc_eh_personality;
311
}
312
 
313
/* --- templates --- */
314
/* struct _objc_selector {
315
     SEL sel_id;
316
     char *sel_type;
317
   }; */
318
 
319
static void
320
build_selector_template (void)
321
{
322
  tree decls, *chain = NULL;
323
 
324
  objc_selector_template = objc_start_struct (get_identifier (UTAG_SELECTOR));
325
 
326
  /* SEL sel_id; */
327
  decls = add_field_decl (objc_selector_type, "sel_id", &chain);
328
 
329
  /* char *sel_type; */
330
  add_field_decl (string_type_node, "sel_type", &chain);
331
 
332
  objc_finish_struct (objc_selector_template, decls);
333
}
334
 
335
/* struct _objc_class {
336
     struct _objc_class *isa;
337
     struct _objc_class *super_class;
338
     char *name;
339
     long version;
340
     long info;
341
     long instance_size;
342
     struct _objc_ivar_list *ivars;
343
     struct _objc_method_list *methods;
344
     struct sarray *dtable;
345
     struct _objc_class *subclass_list;
346
     struct _objc_class *sibling_class;
347
     struct _objc_protocol_list *protocols;
348
     void *gc_object_type;
349
   };  */
350
 
351
static void
352
build_class_template (void)
353
{
354
  tree ptype, decls, *chain = NULL;
355
 
356
  objc_class_template = objc_start_struct (get_identifier (UTAG_CLASS));
357
 
358
  /* struct _objc_class *isa; */
359
  decls = add_field_decl (build_pointer_type (objc_class_template),
360
                          "isa", &chain);
361
 
362
  /* struct _objc_class *super_class; */
363
  add_field_decl (build_pointer_type (objc_class_template),
364
                  "super_class", &chain);
365
 
366
  /* char *name; */
367
  add_field_decl (string_type_node, "name", &chain);
368
 
369
  /* long version; */
370
  add_field_decl (long_integer_type_node, "version", &chain);
371
 
372
  /* long info; */
373
  add_field_decl (long_integer_type_node, "info", &chain);
374
 
375
  /* long instance_size; */
376
  add_field_decl (long_integer_type_node, "instance_size", &chain);
377
 
378
  /* struct _objc_ivar_list *ivars; */
379
  add_field_decl (objc_ivar_list_ptr,"ivars", &chain);
380
 
381
  /* struct _objc_method_list *methods; */
382
  add_field_decl (objc_method_list_ptr, "methods", &chain);
383
 
384
  /* struct sarray *dtable; */
385
  ptype = build_pointer_type(xref_tag (RECORD_TYPE,
386
                                           get_identifier ("sarray")));
387
  add_field_decl (ptype, "dtable", &chain);
388
 
389
  /* struct objc_class *subclass_list; */
390
  ptype = build_pointer_type (objc_class_template);
391
  add_field_decl (ptype, "subclass_list", &chain);
392
 
393
  /* struct objc_class *sibling_class; */
394
  ptype = build_pointer_type (objc_class_template);
395
  add_field_decl (ptype, "sibling_class", &chain);
396
 
397
  /* struct _objc_protocol **protocol_list; */
398
  ptype = build_pointer_type (build_pointer_type
399
                              (xref_tag (RECORD_TYPE,
400
                                         get_identifier (UTAG_PROTOCOL))));
401
  add_field_decl (ptype, "protocol_list", &chain);
402
 
403
  /* void *gc_object_type; */
404
  add_field_decl (build_pointer_type (void_type_node),
405
                    "gc_object_type", &chain);
406
 
407
  objc_finish_struct (objc_class_template, decls);
408
}
409
 
410
/* struct _objc_category {
411
     char *category_name;
412
     char *class_name;
413
     struct _objc_method_list *instance_methods;
414
     struct _objc_method_list *class_methods;
415
     struct _objc_protocol_list *protocols;
416
   };   */
417
 
418
static void
419
build_category_template (void)
420
{
421
  tree ptype, decls, *chain = NULL;
422
 
423
  objc_category_template = objc_start_struct (get_identifier (UTAG_CATEGORY));
424
 
425
  /* char *category_name; */
426
  decls = add_field_decl (string_type_node, "category_name", &chain);
427
 
428
  /* char *class_name; */
429
  add_field_decl (string_type_node, "class_name", &chain);
430
 
431
  /* struct _objc_method_list *instance_methods; */
432
  add_field_decl (objc_method_list_ptr, "instance_methods", &chain);
433
 
434
  /* struct _objc_method_list *class_methods; */
435
  add_field_decl (objc_method_list_ptr, "class_methods", &chain);
436
 
437
  /* struct _objc_protocol **protocol_list; */
438
  ptype = build_pointer_type (build_pointer_type (objc_protocol_template));
439
  add_field_decl (ptype, "protocol_list", &chain);
440
 
441
  objc_finish_struct (objc_category_template, decls);
442
}
443
 
444
/* struct _objc_protocol {
445
     struct _objc_class *isa;
446
     char *protocol_name;
447
     struct _objc_protocol **protocol_list;
448
     struct _objc__method_prototype_list *instance_methods;
449
     struct _objc__method_prototype_list *class_methods;
450
   };  */
451
 
452
static void
453
build_protocol_template (void)
454
{
455
  tree ptype, decls, *chain = NULL;
456
 
457
  objc_protocol_template = objc_start_struct (get_identifier (UTAG_PROTOCOL));
458
 
459
  /* struct _objc_class *isa; */
460
  ptype = build_pointer_type (xref_tag (RECORD_TYPE,
461
                                        get_identifier (UTAG_CLASS)));
462
  decls = add_field_decl (ptype, "isa", &chain);
463
 
464
  /* char *protocol_name; */
465
  add_field_decl (string_type_node, "protocol_name", &chain);
466
 
467
  /* struct _objc_protocol **protocol_list; */
468
  ptype = build_pointer_type (build_pointer_type (objc_protocol_template));
469
  add_field_decl (ptype, "protocol_list", &chain);
470
 
471
  /* struct _objc__method_prototype_list *instance_methods; */
472
  add_field_decl (objc_method_proto_list_ptr, "instance_methods", &chain);
473
 
474
  /* struct _objc__method_prototype_list *class_methods; */
475
  add_field_decl (objc_method_proto_list_ptr, "class_methods", &chain);
476
 
477
  objc_finish_struct (objc_protocol_template, decls);
478
}
479
 
480
/* --- names, decls + identifers --- */
481
 
482
static void
483
build_selector_table_decl (void)
484
{
485
  tree temp;
486
 
487
  build_selector_template ();
488
  temp = build_array_type (objc_selector_template, NULL_TREE);
489
 
490
  UOBJC_SELECTOR_TABLE_decl = start_var_decl (temp, "_OBJC_SELECTOR_TABLE");
491
  OBJCMETA (UOBJC_SELECTOR_TABLE_decl, objc_meta, meta_base);
492
}
493
 
494
 
495
static tree
496
gnu_runtime_abi_01_super_superclassfield_id (void)
497
{
498
  if (!super_superclassfield_id)
499
    super_superclassfield_id = get_identifier ("super_class");
500
  return super_superclassfield_id;
501
}
502
 
503
 
504
static tree
505
gnu_runtime_abi_01_class_decl (tree klass)
506
{
507
  tree decl;
508
  char buf[BUFSIZE];
509
  snprintf (buf, BUFSIZE, "_OBJC_Class_%s",
510
            IDENTIFIER_POINTER (CLASS_NAME (klass)));
511
  decl = start_var_decl (objc_class_template, buf);
512
  OBJCMETA (decl, objc_meta, meta_base);
513
  return decl;
514
}
515
 
516
static tree
517
gnu_runtime_abi_01_metaclass_decl (tree klass)
518
{
519
  tree decl;
520
  char buf[BUFSIZE];
521
  snprintf (buf, BUFSIZE, "_OBJC_MetaClass_%s",
522
            IDENTIFIER_POINTER (CLASS_NAME (klass)));
523
  decl = start_var_decl (objc_class_template, buf);
524
  OBJCMETA (decl, objc_meta, meta_base);
525
  return decl;
526
}
527
 
528
static tree
529
gnu_runtime_abi_01_category_decl (tree klass)
530
{
531
  tree decl;
532
  char buf[BUFSIZE];
533
  snprintf (buf, BUFSIZE, "_OBJC_Category_%s_on_%s",
534
            IDENTIFIER_POINTER (CLASS_SUPER_NAME (klass)),
535
            IDENTIFIER_POINTER (CLASS_NAME (klass)));
536
  decl = start_var_decl (objc_category_template, buf);
537
  OBJCMETA (decl, objc_meta, meta_base);
538
  return decl;
539
}
540
 
541
static tree
542
gnu_runtime_abi_01_protocol_decl (tree p)
543
{
544
  tree decl;
545
  char buf[BUFSIZE];
546
 
547
  /* static struct _objc_protocol _OBJC_Protocol_<mumble>; */
548
  snprintf (buf, BUFSIZE, "_OBJC_Protocol_%s",
549
            IDENTIFIER_POINTER (PROTOCOL_NAME (p)));
550
  decl = start_var_decl (objc_protocol_template, buf);
551
  OBJCMETA (decl, objc_meta, meta_base);
552
  return decl;
553
}
554
 
555
static tree
556
gnu_runtime_abi_01_string_decl (tree type, const char *name,
557
                                string_section where ATTRIBUTE_UNUSED)
558
{
559
  tree decl = start_var_decl (type, name);
560
  OBJCMETA (decl, objc_meta, meta_base);
561
  return decl;
562
}
563
 
564
/* --- entry --- */
565
 
566
static tree
567
gnu_runtime_abi_01_get_class_reference (tree ident)
568
{
569
  tree params;
570
 
571
  add_class_reference (ident);
572
 
573
  params = build_tree_list (NULL_TREE, my_build_string_pointer
574
                                                (IDENTIFIER_LENGTH (ident) + 1,
575
                                                 IDENTIFIER_POINTER (ident)));
576
 
577
  /* FIXME: Do we need this assemble_external() ? */
578
  /* assemble_external (objc_get_class_decl);*/
579
  return build_function_call (input_location, objc_get_class_decl, params);
580
}
581
 
582
/* Used by build_function_type_for_method.  Append the types for
583
   receiver & _cmd at the start of a method argument list to ARGTYPES.
584
   CONTEXT is either METHOD_DEF or METHOD_REF, saying whether we are
585
   trying to define a method or call one.  SUPERFLAG says this is for a
586
   send to super.  METH may be NULL, in the case that there is no
587
   prototype.  */
588
 
589
static void
590
gnu_runtime_abi_01_get_arg_type_list_base (VEC(tree,gc) **argtypes, tree meth,
591
                                           int context,
592
                                           int superflag ATTRIBUTE_UNUSED)
593
{
594
  tree receiver_type;
595
 
596
  if (context == METHOD_DEF && TREE_CODE (meth) == INSTANCE_METHOD_DECL)
597
    receiver_type = objc_instance_type;
598
  else
599
    receiver_type = objc_object_type;
600
 
601
  VEC_safe_push (tree, gc, *argtypes, receiver_type);
602
  /* Selector type - will eventually change to `int'.  */
603
  VEC_safe_push (tree, gc, *argtypes, objc_selector_type);
604
}
605
 
606
/* Unused for GNU runtime.  */
607
static tree
608
gnu_runtime_abi_01_receiver_is_class_object (tree a ATTRIBUTE_UNUSED)
609
{
610
  return NULL_TREE;
611
}
612
 
613
/* sel_ref_chain is a list whose "value" fields will be instances of
614
   identifier_node that represent the selector.  LOC is the location of
615
   the @selector.  */
616
 
617
static tree
618
gnu_runtime_abi_01_build_typed_selector_reference (location_t loc, tree ident,
619
                                                   tree prototype)
620
{
621
  tree *chain = &sel_ref_chain;
622
  tree expr;
623
  int index = 0;
624
 
625
  while (*chain)
626
    {
627
      /* When we do a lookup for @selector () we have no idea of the
628
         prototype - so match the first we find.  */
629
      if (TREE_VALUE (*chain) == ident
630
          && (!prototype || TREE_PURPOSE (*chain) == prototype))
631
        goto return_at_index;
632
 
633
      index++;
634
      chain = &TREE_CHAIN (*chain);
635
    }
636
 
637
  *chain = tree_cons (prototype, ident, NULL_TREE);
638
 
639
  /* TODO: Use a vec and keep this in it to (a) avoid re-creating and
640
     (b) provide better diagnostics for the first time an undefined
641
     selector is used.  */
642
 return_at_index:
643
  expr = build_unary_op (loc, ADDR_EXPR,
644
                         build_array_ref (loc, UOBJC_SELECTOR_TABLE_decl,
645
                                          build_int_cst (NULL_TREE, index)),
646
                         1);
647
  return convert (objc_selector_type, expr);
648
}
649
 
650
/* Build a tree expression to send OBJECT the operation SELECTOR,
651
   looking up the method on object LOOKUP_OBJECT (often same as OBJECT),
652
   assuming the method has prototype METHOD_PROTOTYPE.
653
   (That is an INSTANCE_METHOD_DECL or CLASS_METHOD_DECL.)
654
   LOC is the location of the expression to build.
655
   Use METHOD_PARAMS as list of args to pass to the method.
656
   If SUPER_FLAG is nonzero, we look up the superclass's method.  */
657
 
658
static tree
659
build_objc_method_call (location_t loc, int super_flag, tree method_prototype,
660
                        tree lookup_object, tree selector,
661
                        tree method_params)
662
{
663
  tree sender = (super_flag ? umsg_super_decl
664
                            : (flag_objc_direct_dispatch ? umsg_fast_decl
665
                                                         : umsg_decl));
666
  tree rcv_p = (super_flag ? objc_super_type : objc_object_type);
667
  VEC(tree, gc) *parms;
668
  VEC(tree, gc) *tv;
669
  unsigned nparm = (method_params ? list_length (method_params) : 0);
670
 
671
  /* If a prototype for the method to be called exists, then cast
672
     the sender's return type and arguments to match that of the method.
673
     Otherwise, leave sender as is.  */
674
  tree ret_type
675
    = (method_prototype
676
       ? TREE_VALUE (TREE_TYPE (method_prototype))
677
       : objc_object_type);
678
  tree ftype
679
    = build_function_type_for_method (ret_type, method_prototype,
680
                                      METHOD_REF, super_flag);
681
  tree sender_cast;
682
  tree method, t;
683
 
684
  if (method_prototype && METHOD_TYPE_ATTRIBUTES (method_prototype))
685
    ftype = build_type_attribute_variant (ftype,
686
                                          METHOD_TYPE_ATTRIBUTES
687
                                          (method_prototype));
688
 
689
  sender_cast = build_pointer_type (ftype);
690
 
691
  lookup_object = build_c_cast (loc, rcv_p, lookup_object);
692
 
693
  /* Use SAVE_EXPR to avoid evaluating the receiver twice.  */
694
  lookup_object = save_expr (lookup_object);
695
 
696
  /* Param list + 2 slots for object and selector.  */
697
  parms = VEC_alloc (tree, gc, nparm + 2);
698
  tv = VEC_alloc (tree, gc, 2);
699
 
700
  /* First, call the lookup function to get a pointer to the method,
701
     then cast the pointer, then call it with the method arguments.  */
702
  VEC_quick_push (tree, tv, lookup_object);
703
  VEC_quick_push (tree, tv, selector);
704
  method = build_function_call_vec (loc, sender, tv, NULL);
705
  VEC_free (tree, gc, tv);
706
 
707
  /* Pass the appropriate object to the method.  */
708
  VEC_quick_push (tree, parms, (super_flag ? self_decl : lookup_object));
709
 
710
  /* Pass the selector to the method.  */
711
  VEC_quick_push (tree, parms, selector);
712
  /* Now append the remainder of the parms.  */
713
  if (nparm)
714
    for (; method_params; method_params = TREE_CHAIN (method_params))
715
      VEC_quick_push (tree, parms, TREE_VALUE (method_params));
716
 
717
  /* Build an obj_type_ref, with the correct cast for the method call.  */
718
  t = build3 (OBJ_TYPE_REF, sender_cast, method, lookup_object, size_zero_node);
719
  t = build_function_call_vec (loc, t, parms, NULL);
720
  VEC_free (tree, gc, parms);
721
  return t;
722
}
723
 
724
static tree
725
gnu_runtime_abi_01_build_objc_method_call (location_t loc,
726
                                           tree method_prototype,
727
                                           tree receiver,
728
                                           tree rtype ATTRIBUTE_UNUSED,
729
                                           tree sel_name,
730
                                           tree method_params,
731
                                           int super ATTRIBUTE_UNUSED)
732
{
733
  tree selector =
734
        gnu_runtime_abi_01_build_typed_selector_reference (loc,
735
                                                          sel_name,
736
                                                          method_prototype);
737
 
738
  return build_objc_method_call (loc, super, method_prototype, receiver,
739
                                 selector, method_params);
740
}
741
 
742
static tree
743
gnu_runtime_abi_01_get_protocol_reference (location_t loc, tree p)
744
{
745
  tree expr, protocol_struct_type, *chain;
746
  if (!PROTOCOL_FORWARD_DECL (p))
747
    PROTOCOL_FORWARD_DECL (p) = gnu_runtime_abi_01_protocol_decl (p);
748
 
749
  expr = build_unary_op (loc, ADDR_EXPR, PROTOCOL_FORWARD_DECL (p), 0);
750
 
751
  /* ??? Ideally we'd build the reference with objc_protocol_type directly,
752
     if we have it, rather than converting it here.  */
753
  expr = convert (objc_protocol_type, expr);
754
 
755
  /* The @protocol() expression is being compiled into a pointer to a
756
     statically allocated instance of the Protocol class.  To become
757
     usable at runtime, the 'isa' pointer of the instance need to be
758
     fixed up at runtime by the runtime library, to point to the
759
     actual 'Protocol' class.  */
760
 
761
  /* For the GNU runtime, put the static Protocol instance in the list
762
     of statically allocated instances, so that we make sure that its
763
     'isa' pointer is fixed up at runtime by the GNU runtime library
764
     to point to the Protocol class (at runtime, when loading the
765
     module, the GNU runtime library loops on the statically allocated
766
     instances (as found in the defs field in objc_symtab) and fixups
767
     all the 'isa' pointers of those objects).  */
768
 
769
  /* This type is a struct containing the fields of a Protocol
770
     object.  (Cfr. objc_protocol_type instead is the type of a pointer
771
     to such a struct).  */
772
  protocol_struct_type = xref_tag (RECORD_TYPE,
773
                                   get_identifier (PROTOCOL_OBJECT_CLASS_NAME));
774
 
775
  /* Look for the list of Protocol statically allocated instances
776
     to fixup at runtime.  Create a new list to hold Protocol
777
     statically allocated instances, if the list is not found.  At
778
     present there is only another list, holding NSConstantString
779
     static instances to be fixed up at runtime.  */
780
 
781
  for (chain = &objc_static_instances;
782
        *chain && TREE_VALUE (*chain) != protocol_struct_type;
783
        chain = &TREE_CHAIN (*chain));
784
 
785
  if (!*chain)
786
    {
787
       *chain = tree_cons (NULL_TREE, protocol_struct_type, NULL_TREE);
788
       add_objc_string (OBJC_TYPE_NAME (protocol_struct_type),
789
                          class_names);
790
    }
791
 
792
  /* Add this statically allocated instance to the Protocol list.  */
793
  TREE_PURPOSE (*chain) = tree_cons (NULL_TREE,
794
                                     PROTOCOL_FORWARD_DECL (p),
795
                                     TREE_PURPOSE (*chain));
796
  return expr;
797
}
798
 
799
/* For ABI 8 an IVAR is just a fixed offset in the class struct.  */
800
 
801
static tree
802
gnu_runtime_abi_01_build_ivar_ref (location_t loc ATTRIBUTE_UNUSED,
803
                                   tree base, tree id)
804
{
805
  return objc_build_component_ref (base, id);
806
}
807
 
808
/* We build super class references as we need them (but keep them once
809
   built for the sake of efficiency).  */
810
 
811
static tree
812
gnu_runtime_abi_01_get_class_super_ref (location_t loc ATTRIBUTE_UNUSED,
813
                                        struct imp_entry *imp, bool inst_meth)
814
{
815
  if (inst_meth)
816
    {
817
      if (!ucls_super_ref)
818
        ucls_super_ref =
819
                objc_build_component_ref (imp->class_decl,
820
                                          get_identifier ("super_class"));
821
        return ucls_super_ref;
822
    }
823
  else
824
    {
825
      if (!uucls_super_ref)
826
        uucls_super_ref =
827
                objc_build_component_ref (imp->meta_decl,
828
                                          get_identifier ("super_class"));
829
        return uucls_super_ref;
830
    }
831
}
832
 
833
static tree
834
gnu_runtime_abi_01_get_category_super_ref (location_t loc ATTRIBUTE_UNUSED,
835
                                           struct imp_entry *imp, bool inst_meth)
836
{
837
  tree super_name = CLASS_SUPER_NAME (imp->imp_template);
838
  tree super_class;
839
 
840
  add_class_reference (super_name);
841
  super_class = (inst_meth ? objc_get_class_decl : objc_get_meta_class_decl);
842
  /* FIXME: Do we need this assemble_external() ? */
843
  /* assemble_external (super_class);*/
844
  super_name = my_build_string_pointer (IDENTIFIER_LENGTH (super_name) + 1,
845
                                        IDENTIFIER_POINTER (super_name));
846
  /* super_class = get_{meta_}class("CLASS_SUPER_NAME");  */
847
  return build_function_call (input_location,
848
                              super_class,
849
                              build_tree_list (NULL_TREE, super_name));
850
}
851
 
852
static bool
853
gnu_runtime_abi_01_setup_const_string_class_decl (void)
854
{
855
  /* Do nothing, and create no error.  */
856
  return true;
857
}
858
 
859
/* Declare a static instance of CLASS_DECL initialized by CONSTRUCTOR.  */
860
 
861
static GTY(()) int num_static_inst;
862
 
863
static tree
864
objc_add_static_instance (tree constructor, tree class_decl)
865
{
866
  tree *chain, decl;
867
  char buf[BUFSIZE];
868
 
869
  /* Find the list of static instances for the CLASS_DECL.  Create one if
870
     not found.  */
871
  for (chain = &objc_static_instances;
872
       *chain && TREE_VALUE (*chain) != class_decl;
873
       chain = &TREE_CHAIN (*chain));
874
  if (!*chain)
875
    {
876
      *chain = tree_cons (NULL_TREE, class_decl, NULL_TREE);
877
      add_objc_string (OBJC_TYPE_NAME (class_decl), class_names);
878
    }
879
 
880
  snprintf (buf, BUFSIZE, "_OBJC_INSTANCE_%d", num_static_inst++);
881
  decl = build_decl (input_location,
882
                     VAR_DECL, get_identifier (buf), class_decl);
883
  TREE_STATIC (decl) = 1;
884
  DECL_ARTIFICIAL (decl) = 1;
885
  TREE_USED (decl) = 1;
886
  DECL_INITIAL (decl) = constructor;
887
  DECL_CONTEXT (decl) = NULL;
888
  OBJCMETA (decl, objc_meta, meta_base);
889
 
890
  /* We may be writing something else just now.
891
     Postpone till end of input. */
892
  DECL_DEFER_OUTPUT (decl) = 1;
893
  pushdecl_top_level (decl);
894
  rest_of_decl_compilation (decl, 1, 0);
895
 
896
  /* Add the DECL to the head of this CLASS' list.  */
897
  TREE_PURPOSE (*chain) = tree_cons (NULL_TREE, decl, TREE_PURPOSE (*chain));
898
 
899
  return decl;
900
}
901
 
902
static tree
903
gnu_runtime_abi_01_build_const_string_constructor (location_t loc, tree string,
904
                                                   int length)
905
{
906
  tree constructor, fields;
907
  VEC(constructor_elt,gc) *v = NULL;
908
 
909
  /* GNU:    (NXConstantString *) & ((__builtin_ObjCString) { NULL, string, length })  */
910
  fields = TYPE_FIELDS (internal_const_str_type);
911
  CONSTRUCTOR_APPEND_ELT (v, fields, build_int_cst (NULL_TREE, 0));
912
 
913
  fields = DECL_CHAIN (fields);
914
  CONSTRUCTOR_APPEND_ELT (v, fields, build_unary_op (loc,
915
                                                     ADDR_EXPR, string, 1));
916
 
917
  fields = DECL_CHAIN (fields);
918
  CONSTRUCTOR_APPEND_ELT (v, fields, build_int_cst (NULL_TREE, length));
919
  constructor = objc_build_constructor (internal_const_str_type, v);
920
 
921
  constructor = objc_add_static_instance (constructor, constant_string_type);
922
  return constructor;
923
}
924
 
925
/* --- metadata - module initializer --- */
926
 
927
/* The GNU runtime requires us to provide a static initializer function
928
   for each module:
929
 
930
   static void __objc_gnu_init (void) {
931
     __objc_exec_class (&L_OBJC_MODULES);
932
   }  */
933
 
934
 
935
static void
936
build_module_initializer_routine (void)
937
{
938
  tree body;
939
 
940
#ifdef OBJCPLUS
941
  push_lang_context (lang_name_c); /* extern "C" */
942
#endif
943
 
944
  objc_push_parm (build_decl (input_location,
945
                              PARM_DECL, NULL_TREE, void_type_node));
946
#ifdef OBJCPLUS
947
  objc_start_function (get_identifier (TAG_GNUINIT),
948
                       build_function_type_list (void_type_node, NULL_TREE),
949
                       NULL_TREE, NULL_TREE);
950
#else
951
  objc_start_function (get_identifier (TAG_GNUINIT),
952
                       build_function_type_list (void_type_node, NULL_TREE),
953
                       NULL_TREE, objc_get_parm_info (0, NULL_TREE));
954
#endif
955
  body = c_begin_compound_stmt (true);
956
  add_stmt (build_function_call
957
            (input_location,
958
             execclass_decl,
959
             build_tree_list
960
             (NULL_TREE,
961
              build_unary_op (input_location, ADDR_EXPR,
962
                              UOBJC_MODULES_decl, 0))));
963
  add_stmt (c_end_compound_stmt (input_location, body, true));
964
 
965
  TREE_PUBLIC (current_function_decl) = 0;
966
 
967
#ifndef OBJCPLUS
968
  /* For Objective-C++, we will need to call __objc_gnu_init
969
     from objc_generate_static_init_call() below.  */
970
  DECL_STATIC_CONSTRUCTOR (current_function_decl) = 1;
971
#endif
972
 
973
  GNU_INIT_decl = current_function_decl;
974
  finish_function ();
975
 
976
#ifdef OBJCPLUS
977
    pop_lang_context ();
978
#endif
979
}
980
 
981
#ifdef OBJCPLUS
982
/* Return 1 if the __objc_gnu_init function has been synthesized and needs
983
   to be called by the module initializer routine.  */
984
 
985
int
986
objc_static_init_needed_p (void)
987
{
988
  return (GNU_INIT_decl != NULL_TREE);
989
}
990
 
991
/* Generate a call to the __objc_gnu_init initializer function.  */
992
 
993
tree
994
objc_generate_static_init_call (tree ctors ATTRIBUTE_UNUSED)
995
{
996
  add_stmt (build_stmt (input_location, EXPR_STMT,
997
                        build_function_call (input_location,
998
                                             GNU_INIT_decl, NULL_TREE)));
999
 
1000
  return ctors;
1001
}
1002
#endif /* OBJCPLUS */
1003
 
1004
/* --- Output GNU Meta-data --- */
1005
 
1006
static void
1007
generate_classref_translation_entry (tree chain)
1008
{
1009
  tree expr, decl, type;
1010
 
1011
  decl = TREE_PURPOSE (chain);
1012
  type = TREE_TYPE (decl);
1013
 
1014
  expr = add_objc_string (TREE_VALUE (chain), class_names);
1015
  expr = convert (type, expr); /* cast! */
1016
 
1017
  /* This is a class reference.  It is re-written by the runtime,
1018
     but will be optimized away unless we force it.  */
1019
  DECL_PRESERVE_P (decl) = 1;
1020
  OBJCMETA (decl, objc_meta, meta_base);
1021
  finish_var_decl (decl, expr);
1022
  return;
1023
}
1024
 
1025
 
1026
static void
1027
handle_impent (struct imp_entry *impent)
1028
{
1029
  char *string;
1030
 
1031
/*  objc_implementation_context = impent->imp_context;
1032
  implementation_template = impent->imp_template;*/
1033
 
1034
  switch (TREE_CODE (impent->imp_context))
1035
    {
1036
    case CLASS_IMPLEMENTATION_TYPE:
1037
      {
1038
        const char *const class_name =
1039
          IDENTIFIER_POINTER (CLASS_NAME (impent->imp_context));
1040
 
1041
        string = (char *) alloca (strlen (class_name) + 30);
1042
 
1043
        sprintf (string, "__objc_class_name_%s", class_name);
1044
        break;
1045
      }
1046
    case CATEGORY_IMPLEMENTATION_TYPE:
1047
      {
1048
        const char *const class_name =
1049
          IDENTIFIER_POINTER (CLASS_NAME (impent->imp_context));
1050
        const char *const class_super_name =
1051
          IDENTIFIER_POINTER (CLASS_SUPER_NAME (impent->imp_context));
1052
 
1053
        string = (char *) alloca (strlen (class_name)
1054
                                  + strlen (class_super_name) + 30);
1055
 
1056
        /* Do the same for categories.  Even though no references to
1057
           these symbols are generated automatically by the compiler,
1058
           it gives you a handle to pull them into an archive by
1059
           hand.  */
1060
        sprintf (string, "*__objc_category_name_%s_%s", class_name, class_super_name);
1061
        break;
1062
      }
1063
    default:
1064
      return;
1065
    }
1066
 
1067
    {
1068
      tree decl, init;
1069
 
1070
      init = integer_zero_node;
1071
      decl = build_decl (input_location,
1072
                         VAR_DECL, get_identifier (string), TREE_TYPE (init));
1073
      TREE_PUBLIC (decl) = 1;
1074
      TREE_READONLY (decl) = 1;
1075
      TREE_USED (decl) = 1;
1076
      TREE_CONSTANT (decl) = 1;
1077
      DECL_CONTEXT (decl) = NULL_TREE;
1078
      DECL_ARTIFICIAL (decl) = 1;
1079
      TREE_STATIC (decl) = 1;
1080
      DECL_INITIAL (decl) = error_mark_node; /* A real initializer is coming... */
1081
      /* We must force the reference.  */
1082
      DECL_PRESERVE_P (decl) = 1;
1083
 
1084
      finish_var_decl(decl, init) ;
1085
    }
1086
}
1087
 
1088
tree
1089
build_protocol_initializer (tree type, tree protocol_name, tree protocol_list,
1090
                            tree inst_methods, tree class_methods)
1091
{
1092
  tree expr, ttyp;
1093
  location_t loc;
1094
  VEC(constructor_elt,gc) *inits = NULL;
1095
 
1096
  /* TODO: pass the loc in or find it from args.  */
1097
  loc = input_location;
1098
  ttyp = build_pointer_type (xref_tag (RECORD_TYPE,
1099
                                       get_identifier (UTAG_CLASS)));
1100
  /* Filling the "isa" in with a version allows the runtime system to
1101
     detect this ...   */
1102
  expr = build_int_cst (ttyp, PROTOCOL_VERSION);
1103
 
1104
  CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, expr);
1105
 
1106
  CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, protocol_name);
1107
  CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, protocol_list);
1108
 
1109
  ttyp = objc_method_proto_list_ptr;
1110
  if (inst_methods)
1111
    expr = convert (ttyp, build_unary_op (loc, ADDR_EXPR, inst_methods, 0));
1112
  else
1113
    expr = convert (ttyp, null_pointer_node);
1114
  CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, expr);
1115
 
1116
  if (class_methods)
1117
    expr = convert (ttyp, build_unary_op (loc, ADDR_EXPR, class_methods, 0));
1118
  else
1119
    expr = convert (ttyp, null_pointer_node);
1120
  CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, expr);
1121
 
1122
  return objc_build_constructor (type, inits);
1123
}
1124
 
1125
static tree
1126
generate_protocol_list (tree i_or_p, tree klass_ctxt)
1127
{
1128
  tree array_type, ptype, refs_decl, lproto, e, plist;
1129
  VEC(constructor_elt,gc) *v = NULL;
1130
  char buf[BUFSIZE];
1131
  int size = 0;
1132
 
1133
  switch (TREE_CODE (i_or_p))
1134
    {
1135
    case CLASS_INTERFACE_TYPE:
1136
    case CATEGORY_INTERFACE_TYPE:
1137
      plist = CLASS_PROTOCOL_LIST (i_or_p);
1138
      break;
1139
    case PROTOCOL_INTERFACE_TYPE:
1140
      plist = PROTOCOL_LIST (i_or_p);
1141
      break;
1142
    default:
1143
      gcc_unreachable ();
1144
    }
1145
 
1146
  /* Compute size.  */
1147
  for (lproto = plist; lproto; lproto = TREE_CHAIN (lproto))
1148
    if (TREE_CODE (TREE_VALUE (lproto)) == PROTOCOL_INTERFACE_TYPE
1149
        && PROTOCOL_FORWARD_DECL (TREE_VALUE (lproto)))
1150
      size++;
1151
 
1152
  /* Build initializer.  */
1153
  CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, build_int_cst (NULL_TREE, 0));
1154
  e = build_int_cst (build_pointer_type (objc_protocol_template), size);
1155
  CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, e);
1156
 
1157
  for (lproto = plist; lproto; lproto = TREE_CHAIN (lproto))
1158
    {
1159
      tree pval = TREE_VALUE (lproto);
1160
 
1161
      if (TREE_CODE (pval) == PROTOCOL_INTERFACE_TYPE
1162
          && PROTOCOL_FORWARD_DECL (pval))
1163
        {
1164
          tree fwref = PROTOCOL_FORWARD_DECL (pval);
1165
          location_t loc = DECL_SOURCE_LOCATION (fwref) ;
1166
          e = build_unary_op (loc, ADDR_EXPR, fwref, 0);
1167
          CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, e);
1168
        }
1169
    }
1170
 
1171
  /* static struct objc_protocol *refs[n]; */
1172
 
1173
  switch (TREE_CODE (i_or_p))
1174
    {
1175
    case PROTOCOL_INTERFACE_TYPE:
1176
      snprintf (buf, BUFSIZE, "_OBJC_ProtocolRefs_%s",
1177
                IDENTIFIER_POINTER (PROTOCOL_NAME (i_or_p)));
1178
      break;
1179
    case CLASS_INTERFACE_TYPE:
1180
      snprintf (buf, BUFSIZE, "_OBJC_ClassProtocols_%s",
1181
                IDENTIFIER_POINTER (CLASS_NAME (i_or_p)));
1182
      break;
1183
    case CATEGORY_INTERFACE_TYPE:
1184
      snprintf (buf, BUFSIZE, "_OBJC_CategoryProtocols_%s_%s",
1185
                IDENTIFIER_POINTER (CLASS_NAME (klass_ctxt)),
1186
                IDENTIFIER_POINTER (CLASS_SUPER_NAME (klass_ctxt)));
1187
      break;
1188
    default:
1189
      gcc_unreachable ();
1190
    }
1191
 
1192
  ptype = build_pointer_type (objc_protocol_template);
1193
  array_type = build_sized_array_type (ptype, size + 3);
1194
  refs_decl = start_var_decl (array_type, buf);
1195
  OBJCMETA (refs_decl, objc_meta, meta_base);
1196
  finish_var_decl (refs_decl,
1197
                   objc_build_constructor (TREE_TYPE (refs_decl), v));
1198
 
1199
  return refs_decl;
1200
}
1201
 
1202
static tree
1203
generate_v1_meth_descriptor_table (tree chain, tree protocol, const char *prefix)
1204
{
1205
  tree method_list_template, initlist, decl;
1206
  int size;
1207
  VEC(constructor_elt,gc) *v = NULL;
1208
  char buf[BUFSIZE];
1209
 
1210
  if (!chain || !prefix)
1211
    return NULL_TREE;
1212
 
1213
  if (!objc_method_prototype_template)
1214
    objc_method_prototype_template = build_method_prototype_template ();
1215
 
1216
  size = list_length (chain);
1217
  method_list_template =
1218
        build_method_prototype_list_template (objc_method_prototype_template,
1219
                                              size);
1220
  snprintf (buf, BUFSIZE, "%s_%s", prefix,
1221
            IDENTIFIER_POINTER (PROTOCOL_NAME (protocol)));
1222
 
1223
  decl = start_var_decl (method_list_template, buf);
1224
 
1225
  CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, build_int_cst (NULL_TREE, size));
1226
  initlist =
1227
        build_descriptor_table_initializer (objc_method_prototype_template,
1228
                                            chain);
1229
  CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, initlist);
1230
  OBJCMETA (decl, objc_meta, meta_base);
1231
  finish_var_decl (decl, objc_build_constructor (method_list_template, v));
1232
  return decl;
1233
}
1234
 
1235
/* For each protocol which was referenced either from a @protocol()
1236
   expression, or because a class/category implements it (then a
1237
   pointer to the protocol is stored in the struct describing the
1238
   class/category), we create a statically allocated instance of the
1239
   Protocol class.  The code is written in such a way as to generate
1240
   as few Protocol objects as possible; we generate a unique Protocol
1241
   instance for each protocol, and we don't generate a Protocol
1242
   instance if the protocol is never referenced (either from a
1243
   @protocol() or from a class/category implementation).  These
1244
   statically allocated objects can be referred to via the static
1245
   (that is, private to this module) symbols _OBJC_PROTOCOL_n.
1246
 
1247
   The statically allocated Protocol objects that we generate here
1248
   need to be fixed up at runtime in order to be used: the 'isa'
1249
   pointer of the objects need to be set up to point to the 'Protocol'
1250
   class, as known at runtime.
1251
 
1252
   The GNU runtime fixes up all protocols before user code from the module
1253
   is executed; it requires pointers to those symbols
1254
   to be put in the objc_symtab (which is then passed as argument to
1255
   the function __objc_exec_class() which the compiler sets up to be
1256
   executed automatically when the module is loaded); setup of those
1257
   Protocol objects happen in two ways in the GNU runtime: all
1258
   Protocol objects referred to by a class or category implementation
1259
   are fixed up when the class/category is loaded; all Protocol
1260
   objects referred to by a @protocol() expression are added by the
1261
   compiler to the list of statically allocated instances to fixup
1262
   (the same list holding the statically allocated constant string
1263
   objects).  Because, as explained above, the compiler generates as
1264
   few Protocol objects as possible, some Protocol object might end up
1265
   being referenced multiple times when compiled with the GNU runtime,
1266
   and end up being fixed up multiple times at runtime initialization.
1267
   But that doesn't hurt, it's just a little inefficient.  */
1268
 
1269
static void
1270
generate_protocols (void)
1271
{
1272
  tree p, encoding;
1273
  tree decl;
1274
  tree initlist, protocol_name_expr, refs_decl, refs_expr;
1275
 
1276
  /* If a protocol was directly referenced, pull in indirect references.  */
1277
  for (p = protocol_chain; p; p = TREE_CHAIN (p))
1278
    if (PROTOCOL_FORWARD_DECL (p) && PROTOCOL_LIST (p))
1279
      generate_protocol_references (PROTOCOL_LIST (p));
1280
 
1281
  for (p = protocol_chain; p; p = TREE_CHAIN (p))
1282
    {
1283
      tree nst_methods = PROTOCOL_NST_METHODS (p);
1284
      tree cls_methods = PROTOCOL_CLS_METHODS (p);
1285
 
1286
      /* If protocol wasn't referenced, don't generate any code.  */
1287
      decl = PROTOCOL_FORWARD_DECL (p);
1288
 
1289
      if (!decl)
1290
        continue;
1291
 
1292
      /* Make sure we link in the Protocol class.  */
1293
      add_class_reference (get_identifier (PROTOCOL_OBJECT_CLASS_NAME));
1294
 
1295
      while (nst_methods)
1296
        {
1297
          if (! METHOD_ENCODING (nst_methods))
1298
            {
1299
              encoding = encode_method_prototype (nst_methods);
1300
              METHOD_ENCODING (nst_methods) = encoding;
1301
            }
1302
          nst_methods = DECL_CHAIN (nst_methods);
1303
        }
1304
 
1305
      UOBJC_INSTANCE_METHODS_decl =
1306
        generate_v1_meth_descriptor_table (PROTOCOL_NST_METHODS (p), p,
1307
                                           "_OBJC_PROTOCOL_INSTANCE_METHODS");
1308
 
1309
      while (cls_methods)
1310
        {
1311
          if (! METHOD_ENCODING (cls_methods))
1312
            {
1313
              encoding = encode_method_prototype (cls_methods);
1314
              METHOD_ENCODING (cls_methods) = encoding;
1315
            }
1316
 
1317
          cls_methods = DECL_CHAIN (cls_methods);
1318
        }
1319
 
1320
      UOBJC_CLASS_METHODS_decl =
1321
        generate_v1_meth_descriptor_table (PROTOCOL_CLS_METHODS (p), p,
1322
                                           "_OBJC_PROTOCOL_CLASS_METHODS");
1323
/*      generate_method_descriptors (p);*/
1324
 
1325
      if (PROTOCOL_LIST (p))
1326
        refs_decl = generate_protocol_list (p, NULL_TREE);
1327
      else
1328
        refs_decl = 0;
1329
 
1330
      /* static struct objc_protocol _OBJC_PROTOCOL_<mumble>; */
1331
      protocol_name_expr = add_objc_string (PROTOCOL_NAME (p), class_names);
1332
 
1333
      if (refs_decl)
1334
        refs_expr = convert (build_pointer_type (build_pointer_type
1335
                                                 (objc_protocol_template)),
1336
                             build_unary_op (input_location,
1337
                                             ADDR_EXPR, refs_decl, 0));
1338
      else
1339
        refs_expr = build_int_cst (NULL_TREE, 0);
1340
 
1341
      /* UOBJC_INSTANCE_METHODS_decl/UOBJC_CLASS_METHODS_decl are set
1342
         by generate_method_descriptors, which is called above.  */
1343
      initlist = build_protocol_initializer (TREE_TYPE (decl),
1344
                                             protocol_name_expr, refs_expr,
1345
                                             UOBJC_INSTANCE_METHODS_decl,
1346
                                             UOBJC_CLASS_METHODS_decl);
1347
      finish_var_decl (decl, initlist);
1348
    }
1349
}
1350
 
1351
static tree
1352
generate_dispatch_table (tree chain, const char *name)
1353
{
1354
  tree decl, method_list_template, initlist;
1355
  VEC(constructor_elt,gc) *v = NULL;
1356
  int size = list_length (chain);
1357
 
1358
  if (!objc_method_template)
1359
    objc_method_template = build_method_template ();
1360
 
1361
  method_list_template = build_method_list_template (objc_method_template,
1362
                                                     size);
1363
  initlist = build_dispatch_table_initializer (objc_method_template, chain);
1364
 
1365
  decl = start_var_decl (method_list_template, name);
1366
 
1367
  CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, integer_zero_node);
1368
  CONSTRUCTOR_APPEND_ELT (v, NULL_TREE,
1369
                          build_int_cst (integer_type_node, size));
1370
  CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, initlist);
1371
 
1372
  OBJCMETA (decl, objc_meta, meta_base);
1373
  finish_var_decl (decl,
1374
                   objc_build_constructor (TREE_TYPE (decl), v));
1375
 
1376
  return decl;
1377
}
1378
 
1379
/* Init a category.  */
1380
static tree
1381
build_category_initializer (tree type, tree cat_name, tree class_name,
1382
                            tree inst_methods, tree class_methods,
1383
                            tree protocol_list)
1384
{
1385
  tree expr, ltyp;
1386
  location_t loc;
1387
  VEC(constructor_elt,gc) *v = NULL;
1388
 
1389
  /* TODO: pass the loc in or find it from args.  */
1390
  /* TODO: pass the loc in or find it from args.  */
1391
  loc = UNKNOWN_LOCATION;
1392
  CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, cat_name);
1393
  CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, class_name);
1394
 
1395
  ltyp = objc_method_list_ptr;
1396
  if (inst_methods)
1397
    expr = convert (ltyp, build_unary_op (loc, ADDR_EXPR, inst_methods, 0));
1398
  else
1399
    expr = convert (ltyp, null_pointer_node);
1400
  CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
1401
 
1402
  if (class_methods)
1403
    expr = convert (ltyp, build_unary_op (loc, ADDR_EXPR, class_methods, 0));
1404
  else
1405
    expr = convert (ltyp, null_pointer_node);
1406
  CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
1407
 
1408
  /* protocol_list = */
1409
  ltyp = build_pointer_type (build_pointer_type (objc_protocol_template));
1410
  if (protocol_list)
1411
    expr = convert (ltyp, build_unary_op (loc, ADDR_EXPR, protocol_list, 0));
1412
  else
1413
    expr = convert (ltyp, null_pointer_node);
1414
  CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
1415
 
1416
  return objc_build_constructor (type, v);
1417
}
1418
 
1419
/* static struct objc_category _OBJC_CATEGORY_<name> = { ... };  */
1420
 
1421
static void
1422
generate_category (struct imp_entry *impent)
1423
{
1424
  tree initlist, cat_name_expr, class_name_expr;
1425
  tree protocol_decl, category, cat_decl;
1426
  tree inst_methods = NULL_TREE, class_methods = NULL_TREE;
1427
  tree cat = impent->imp_context;
1428
  char buf[BUFSIZE];
1429
 
1430
  cat_decl = impent->class_decl;
1431
 
1432
  add_class_reference (CLASS_NAME (cat));
1433
  cat_name_expr = add_objc_string (CLASS_SUPER_NAME (cat), class_names);
1434
 
1435
  class_name_expr = add_objc_string (CLASS_NAME (cat), class_names);
1436
 
1437
  category = lookup_category (impent->imp_template, CLASS_SUPER_NAME (cat));
1438
 
1439
  if (category && CLASS_PROTOCOL_LIST (category))
1440
    {
1441
      generate_protocol_references (CLASS_PROTOCOL_LIST (category));
1442
      protocol_decl = generate_protocol_list (category, cat);
1443
    }
1444
  else
1445
    protocol_decl = 0;
1446
 
1447
  if (CLASS_NST_METHODS (cat))
1448
    {
1449
      snprintf (buf, BUFSIZE, "_OBJC_CategoryInstanceMethods_%s_%s",
1450
                IDENTIFIER_POINTER (CLASS_NAME (cat)),
1451
                IDENTIFIER_POINTER (CLASS_SUPER_NAME (cat)));
1452
      inst_methods = generate_dispatch_table (CLASS_NST_METHODS (cat), buf);
1453
    }
1454
 
1455
  if (CLASS_CLS_METHODS (cat))
1456
    {
1457
      snprintf (buf, BUFSIZE, "_OBJC_CategoryClassMethods_%s_%s",
1458
                IDENTIFIER_POINTER (CLASS_NAME (cat)),
1459
                IDENTIFIER_POINTER (CLASS_SUPER_NAME (cat)));
1460
      class_methods = generate_dispatch_table (CLASS_CLS_METHODS (cat), buf);
1461
    }
1462
 
1463
  initlist = build_category_initializer (TREE_TYPE (cat_decl),
1464
                                         cat_name_expr, class_name_expr,
1465
                                         inst_methods, class_methods,
1466
                                         protocol_decl);
1467
  /* Finish and initialize the forward decl.  */
1468
  finish_var_decl (cat_decl, initlist);
1469
  impent->class_decl = cat_decl;
1470
}
1471
 
1472
/* struct _objc_class {
1473
     struct objc_class *isa;
1474
     struct objc_class *super_class;
1475
     char *name;
1476
     long version;
1477
     long info;
1478
     long instance_size;
1479
     struct objc_ivar_list *ivars;
1480
     struct objc_method_list *methods;
1481
     struct sarray *dtable;
1482
     struct objc_class *subclass_list;
1483
     struct objc_class *sibling_class;
1484
     struct objc_protocol_list *protocols;
1485
     void *gc_object_type;
1486
   };  */
1487
 
1488
static tree
1489
build_shared_structure_initializer (tree type, tree isa, tree super,
1490
                                    tree name, tree size, int status,
1491
                                    tree dispatch_table, tree ivar_list,
1492
                                    tree protocol_list)
1493
{
1494
  tree expr, ltyp;
1495
  VEC(constructor_elt,gc) *v = NULL;
1496
 
1497
  /* isa = */
1498
  CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, isa);
1499
 
1500
  /* super_class = */
1501
  CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, super);
1502
 
1503
  /* name = */
1504
  CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, default_conversion (name));
1505
 
1506
  /* version = */
1507
  CONSTRUCTOR_APPEND_ELT (v, NULL_TREE,
1508
                          build_int_cst (long_integer_type_node, 0));
1509
 
1510
  /* info = */
1511
  CONSTRUCTOR_APPEND_ELT (v, NULL_TREE,
1512
                          build_int_cst (long_integer_type_node, status));
1513
 
1514
  /* instance_size = */
1515
  CONSTRUCTOR_APPEND_ELT (v, NULL_TREE,
1516
                          convert (long_integer_type_node, size));
1517
 
1518
  /* objc_ivar_list = */
1519
  if (!ivar_list)
1520
    CONSTRUCTOR_APPEND_ELT (v, NULL_TREE,
1521
                            build_int_cst (objc_ivar_list_ptr, 0));
1522
  else
1523
    {
1524
      expr = convert (objc_ivar_list_ptr,
1525
                      build_unary_op (input_location, ADDR_EXPR,
1526
                                      ivar_list, 0));
1527
      CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
1528
    }
1529
 
1530
  /* objc_method_list = */
1531
  if (!dispatch_table)
1532
    CONSTRUCTOR_APPEND_ELT (v, NULL_TREE,
1533
                           convert (objc_method_list_ptr, null_pointer_node));
1534
  else
1535
    {
1536
      expr = convert (objc_method_list_ptr,
1537
                      build_unary_op (input_location, ADDR_EXPR,
1538
                                      dispatch_table, 0));
1539
      CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
1540
    }
1541
 
1542
  /* FIXME: Remove NeXT runtime code.  */
1543
  if (flag_next_runtime)
1544
    {
1545
      ltyp = build_pointer_type (xref_tag (RECORD_TYPE,
1546
                                           get_identifier ("objc_cache")));
1547
      /* method_cache = */
1548
      CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, convert (ltyp, null_pointer_node));
1549
    }
1550
  else
1551
    {
1552
      /* dtable = */
1553
      CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, build_int_cst (NULL_TREE, 0));
1554
 
1555
      /* subclass_list = */
1556
      CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, build_int_cst (NULL_TREE, 0));
1557
 
1558
      /* sibling_class = */
1559
      CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, build_int_cst (NULL_TREE, 0));
1560
    }
1561
 
1562
  /* protocol_list = */
1563
  ltyp = build_pointer_type (build_pointer_type (objc_protocol_template));
1564
  if (! protocol_list)
1565
    CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, build_int_cst (ltyp, 0));
1566
  else
1567
    {
1568
      expr = convert (ltyp,
1569
                      build_unary_op (input_location, ADDR_EXPR,
1570
                                      protocol_list, 0));
1571
      CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
1572
    }
1573
 
1574
  /* FIXME: Remove NeXT runtime code.  */
1575
  if (flag_next_runtime)
1576
    /* sel_id = NULL */
1577
    CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, build_int_cst (NULL_TREE, 0));
1578
 
1579
  /* gc_object_type = NULL */
1580
  CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, build_int_cst (NULL_TREE, 0));
1581
 
1582
  return objc_build_constructor (type, v);
1583
}
1584
 
1585
 
1586
static tree
1587
generate_ivars_list (tree chain, const char *name)
1588
{
1589
  tree initlist, ivar_list_template, decl;
1590
  int size;
1591
  VEC(constructor_elt,gc) *inits = NULL;
1592
 
1593
  if (!chain)
1594
    return NULL_TREE;
1595
 
1596
  if (!objc_ivar_template)
1597
    objc_ivar_template = build_ivar_template ();
1598
 
1599
  size = ivar_list_length (chain);
1600
 
1601
  generating_instance_variables = 1;
1602
  ivar_list_template = build_ivar_list_template (objc_ivar_template, size);
1603
  initlist = build_ivar_list_initializer (objc_ivar_template, chain);
1604
  generating_instance_variables = 0;
1605
 
1606
  decl = start_var_decl (ivar_list_template, name);
1607
 
1608
  CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, build_int_cst (NULL_TREE, size));
1609
  CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, initlist);
1610
 
1611
  OBJCMETA (decl, objc_meta, meta_base);
1612
  finish_var_decl (decl,
1613
                   objc_build_constructor (TREE_TYPE (decl), inits));
1614
 
1615
  return decl;
1616
}
1617
 
1618
/* static struct objc_class _OBJC_METACLASS_Foo={ ... };
1619
   static struct objc_class _OBJC_CLASS_Foo={ ... };  */
1620
 
1621
static void
1622
generate_class_structures (struct imp_entry *impent)
1623
{
1624
  tree name_expr, super_expr, root_expr, class_decl, meta_decl;
1625
  tree my_root_id, my_super_id;
1626
  tree cast_type, initlist, protocol_decl;
1627
  tree inst_methods = NULL_TREE, class_methods = NULL_TREE;
1628
  tree chain, inst_ivars = NULL_TREE, class_ivars = NULL_TREE;
1629
  location_t loc;
1630
  char buf[BUFSIZE];
1631
  int cls_flags = 0 ;
1632
 
1633
/*  objc_implementation_context = impent->imp_context;
1634
  implementation_template = impent->imp_template;*/
1635
  class_decl = impent->class_decl;
1636
  meta_decl = impent->meta_decl;
1637
/*  UOBJC_CLASS_decl = impent->class_decl;
1638
  UOBJC_METACLASS_decl = impent->meta_decl;*/
1639
 
1640
  loc = DECL_SOURCE_LOCATION (impent->class_decl);
1641
 
1642
  my_super_id = CLASS_SUPER_NAME (impent->imp_template);
1643
  if (my_super_id)
1644
    {
1645
      add_class_reference (my_super_id);
1646
 
1647
      /* Compute "my_root_id" - this is required for code generation.
1648
         the "isa" for all meta class structures points to the root of
1649
         the inheritance hierarchy (e.g. "__Object")...  */
1650
      my_root_id = my_super_id;
1651
      do
1652
        {
1653
          tree my_root_int = lookup_interface (my_root_id);
1654
 
1655
          if (my_root_int && CLASS_SUPER_NAME (my_root_int))
1656
            my_root_id = CLASS_SUPER_NAME (my_root_int);
1657
          else
1658
            break;
1659
        }
1660
      while (1);
1661
    }
1662
  else
1663
    /* No super class.  */
1664
    my_root_id = CLASS_NAME (impent->imp_template);
1665
 
1666
  cast_type = build_pointer_type (objc_class_template);
1667
  name_expr = add_objc_string (CLASS_NAME (impent->imp_template),
1668
                               class_names);
1669
 
1670
  /* Install class `isa' and `super' pointers at runtime.  */
1671
  if (my_super_id)
1672
    super_expr = add_objc_string (my_super_id, class_names);
1673
  else
1674
    super_expr = null_pointer_node;
1675
 
1676
  super_expr = build_c_cast (loc, cast_type, super_expr);
1677
 
1678
  root_expr = add_objc_string (my_root_id, class_names);
1679
  root_expr = build_c_cast (loc, cast_type, root_expr);
1680
 
1681
  if (CLASS_PROTOCOL_LIST (impent->imp_template))
1682
    {
1683
      generate_protocol_references (CLASS_PROTOCOL_LIST (impent->imp_template));
1684
      protocol_decl = generate_protocol_list (impent->imp_template,
1685
                                              impent->imp_context);
1686
    }
1687
  else
1688
    protocol_decl = NULL_TREE;
1689
 
1690
  if (CLASS_CLS_METHODS (impent->imp_context))
1691
    {
1692
      snprintf (buf, BUFSIZE, "_OBJC_ClassMethods_%s",
1693
                IDENTIFIER_POINTER (CLASS_NAME (impent->imp_context)));
1694
      class_methods = generate_dispatch_table (CLASS_CLS_METHODS (impent->imp_context),
1695
                                               buf);
1696
    }
1697
 
1698
  if (CLASS_SUPER_NAME (impent->imp_template) == NULL_TREE
1699
      && (chain = TYPE_FIELDS (objc_class_template)))
1700
    {
1701
      snprintf (buf, BUFSIZE, "_OBJC_ClassIvars_%s",
1702
                IDENTIFIER_POINTER (CLASS_NAME (impent->imp_context)));
1703
      class_ivars = generate_ivars_list (chain, buf);
1704
    }
1705
 
1706
  /* static struct objc_class _OBJC_METACLASS_Foo = { ... }; */
1707
 
1708
  initlist =
1709
        build_shared_structure_initializer
1710
                        (TREE_TYPE (meta_decl),
1711
                        root_expr, super_expr, name_expr,
1712
                        convert (integer_type_node,
1713
                                TYPE_SIZE_UNIT (objc_class_template)),
1714
                        CLS_META, class_methods, class_ivars,
1715
                        protocol_decl);
1716
 
1717
  finish_var_decl (meta_decl, initlist);
1718
  impent->meta_decl = meta_decl;
1719
 
1720
  /* static struct objc_class _OBJC_CLASS_Foo={ ... }; */
1721
  if (CLASS_NST_METHODS (impent->imp_context))
1722
    {
1723
      snprintf (buf, BUFSIZE, "_OBJC_InstanceMethods_%s",
1724
                IDENTIFIER_POINTER (CLASS_NAME (impent->imp_context)));
1725
      inst_methods = generate_dispatch_table (CLASS_NST_METHODS (impent->imp_context),
1726
                                              buf);
1727
    }
1728
 
1729
  if ((chain = CLASS_IVARS (impent->imp_template)))
1730
    {
1731
      snprintf (buf, BUFSIZE, "_OBJC_InstanceIvars_%s",
1732
                IDENTIFIER_POINTER (CLASS_NAME (impent->imp_context)));
1733
      inst_ivars = generate_ivars_list (chain, buf);
1734
    }
1735
 
1736
  initlist =
1737
        build_shared_structure_initializer
1738
                (TREE_TYPE (class_decl),
1739
                build_unary_op (loc, ADDR_EXPR, meta_decl, 0),
1740
                super_expr, name_expr,
1741
                convert (integer_type_node,
1742
                         TYPE_SIZE_UNIT (CLASS_STATIC_TEMPLATE
1743
                                        (impent->imp_template))),
1744
                CLS_FACTORY | cls_flags, inst_methods, inst_ivars,
1745
                protocol_decl);
1746
 
1747
  finish_var_decl (class_decl, initlist);
1748
  impent->class_decl = class_decl;
1749
}
1750
 
1751
/* --- Output GNU Metadata --- */
1752
 
1753
/* TODO: Make this into an array of refs.  */
1754
static void
1755
handle_class_ref (tree chain)
1756
{
1757
  const char *name = IDENTIFIER_POINTER (TREE_VALUE (chain));
1758
  char *string = (char *) alloca (strlen (name) + 30);
1759
  tree decl;
1760
  tree exp;
1761
 
1762
  sprintf (string, "__objc_class_name_%s", name);
1763
 
1764
  /* Make a decl for this name, so we can use its address in a tree.  */
1765
  decl = build_decl (input_location,
1766
                     VAR_DECL, get_identifier (string), TREE_TYPE (integer_zero_node));
1767
  DECL_EXTERNAL (decl) = 1;
1768
  TREE_PUBLIC (decl) = 1;
1769
  DECL_CONTEXT (decl) = NULL_TREE;
1770
  finish_var_decl (decl, 0);
1771
 
1772
  /* Make a decl for the address.  */
1773
  sprintf (string, "__objc_class_ref_%s", name);
1774
  exp = build1 (ADDR_EXPR, string_type_node, decl);
1775
  decl = build_decl (input_location,
1776
                     VAR_DECL, get_identifier (string), string_type_node);
1777
  TREE_STATIC (decl) = 1;
1778
  TREE_USED (decl) = 1;
1779
  DECL_READ_P (decl) = 1;
1780
  DECL_ARTIFICIAL (decl) = 1;
1781
  DECL_INITIAL (decl) = error_mark_node;
1782
 
1783
  /* We must force the reference.  */
1784
  DECL_PRESERVE_P (decl) = 1;
1785
 
1786
  DECL_CONTEXT (decl) = NULL_TREE;
1787
  finish_var_decl (decl, exp);
1788
}
1789
 
1790
static tree
1791
get_proto_encoding (tree proto)
1792
{
1793
  tree encoding;
1794
  if (proto)
1795
    {
1796
      if (! METHOD_ENCODING (proto))
1797
        {
1798
          encoding = encode_method_prototype (proto);
1799
          METHOD_ENCODING (proto) = encoding;
1800
        }
1801
      else
1802
        encoding = METHOD_ENCODING (proto);
1803
 
1804
      return add_objc_string (encoding, meth_var_types);
1805
    }
1806
  else
1807
    return build_int_cst (NULL_TREE, 0);
1808
}
1809
 
1810
static void
1811
build_gnu_selector_translation_table (void)
1812
{
1813
  tree chain, expr;
1814
  VEC(constructor_elt,gc) *inits = NULL;
1815
  VEC(constructor_elt,gc) *v ;
1816
 
1817
  /* Cause the selector table (previously forward-declared)
1818
     to be actually output.  */
1819
 
1820
  for (chain = sel_ref_chain; chain; chain = TREE_CHAIN (chain))
1821
    {
1822
      tree encoding;
1823
      if (warn_selector)
1824
        {
1825
          /* TODO: improve on the location for the diagnostic.  */
1826
          location_t loc = input_location;
1827
          diagnose_missing_method (TREE_VALUE (chain), loc);
1828
        }
1829
 
1830
      v = NULL;
1831
      expr = build_selector (TREE_VALUE (chain));
1832
      encoding = get_proto_encoding (TREE_PURPOSE (chain));
1833
      CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
1834
      CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, encoding);
1835
      expr = objc_build_constructor (objc_selector_template, v);
1836
 
1837
      CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, expr);
1838
    } /* each element in the chain */
1839
 
1840
  /* List terminator.  */
1841
  v = NULL;
1842
  CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, integer_zero_node);
1843
  CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, integer_zero_node);
1844
  expr = objc_build_constructor (objc_selector_template, v);
1845
 
1846
  CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, expr);
1847
  expr = objc_build_constructor (TREE_TYPE (UOBJC_SELECTOR_TABLE_decl),
1848
                                     inits);
1849
  finish_var_decl (UOBJC_SELECTOR_TABLE_decl, expr);
1850
}
1851
 
1852
/* Output references to all statically allocated objects.  Return the DECL
1853
   for the array built.  */
1854
 
1855
static void
1856
generate_static_references (void)
1857
{
1858
  tree expr = NULL_TREE;
1859
  tree class_name, klass, decl;
1860
  tree cl_chain, in_chain, type
1861
    = build_array_type (build_pointer_type (void_type_node), NULL_TREE);
1862
  int num_inst, num_class;
1863
  char buf[BUFSIZE];
1864
  VEC(constructor_elt,gc) *decls = NULL;
1865
 
1866
  /* FIXME: Remove NeXT runtime code.  */
1867
  if (flag_next_runtime)
1868
    gcc_unreachable ();
1869
 
1870
  for (cl_chain = objc_static_instances, num_class = 0;
1871
       cl_chain; cl_chain = TREE_CHAIN (cl_chain), num_class++)
1872
    {
1873
      VEC(constructor_elt,gc) *v = NULL;
1874
 
1875
      for (num_inst = 0, in_chain = TREE_PURPOSE (cl_chain);
1876
           in_chain; num_inst++, in_chain = TREE_CHAIN (in_chain));
1877
 
1878
      snprintf (buf, BUFSIZE, "_OBJC_STATIC_INSTANCES_%d", num_class);
1879
      decl = start_var_decl (type, buf);
1880
 
1881
      /* Output {class_name, ...}.  */
1882
      klass = TREE_VALUE (cl_chain);
1883
      class_name = get_objc_string_decl (OBJC_TYPE_NAME (klass), class_names);
1884
      CONSTRUCTOR_APPEND_ELT (v, NULL_TREE,
1885
                              build_unary_op (input_location,
1886
                                              ADDR_EXPR, class_name, 1));
1887
 
1888
      /* Output {..., instance, ...}.  */
1889
      for (in_chain = TREE_PURPOSE (cl_chain);
1890
           in_chain; in_chain = TREE_CHAIN (in_chain))
1891
        {
1892
          expr = build_unary_op (input_location,
1893
                                 ADDR_EXPR, TREE_VALUE (in_chain), 1);
1894
          CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
1895
        }
1896
 
1897
      /* Output {..., NULL}.  */
1898
      CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, build_int_cst (NULL_TREE, 0));
1899
 
1900
      expr = objc_build_constructor (TREE_TYPE (decl), v);
1901
      OBJCMETA (decl, objc_meta, meta_base);
1902
      finish_var_decl (decl, expr);
1903
      CONSTRUCTOR_APPEND_ELT (decls, NULL_TREE,
1904
                              build_unary_op (input_location,
1905
                                              ADDR_EXPR, decl, 1));
1906
    }
1907
 
1908
  CONSTRUCTOR_APPEND_ELT (decls, NULL_TREE, build_int_cst (NULL_TREE, 0));
1909
  expr = objc_build_constructor (type, decls);
1910
  static_instances_decl = start_var_decl (type, "_OBJC_STATIC_INSTANCES");
1911
  OBJCMETA (static_instances_decl, objc_meta, meta_base);
1912
  finish_var_decl (static_instances_decl, expr);
1913
}
1914
 
1915
/* Create the initial value for the `defs' field of _objc_symtab.
1916
   This is a CONSTRUCTOR.  */
1917
 
1918
static tree
1919
init_def_list (tree type)
1920
{
1921
  tree expr;
1922
  struct imp_entry *impent;
1923
  location_t loc;
1924
  VEC(constructor_elt,gc) *v = NULL;
1925
 
1926
  if (imp_count)
1927
    for (impent = imp_list; impent; impent = impent->next)
1928
      {
1929
        if (TREE_CODE (impent->imp_context) == CLASS_IMPLEMENTATION_TYPE)
1930
          {
1931
            loc = DECL_SOURCE_LOCATION (impent->class_decl);
1932
            expr = build_unary_op (loc,
1933
                                   ADDR_EXPR, impent->class_decl, 0);
1934
            CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
1935
          }
1936
      }
1937
 
1938
  if (cat_count)
1939
    for (impent = imp_list; impent; impent = impent->next)
1940
      {
1941
        if (TREE_CODE (impent->imp_context) == CATEGORY_IMPLEMENTATION_TYPE)
1942
          {
1943
            loc = DECL_SOURCE_LOCATION (impent->class_decl);
1944
            expr = build_unary_op (loc,
1945
                                   ADDR_EXPR, impent->class_decl, 0);
1946
            CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
1947
          }
1948
      }
1949
 
1950
  loc = UNKNOWN_LOCATION;
1951
  /* statics = { ..., _OBJC_STATIC_INSTANCES, ... }  */
1952
  if (static_instances_decl)
1953
    expr = build_unary_op (loc, ADDR_EXPR, static_instances_decl, 0);
1954
  else
1955
    expr = integer_zero_node;
1956
  CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
1957
 
1958
  return objc_build_constructor (type, v);
1959
}
1960
 
1961
/* Take care of defining and initializing _OBJC_SYMBOLS.  */
1962
 
1963
/* Predefine the following data type:
1964
 
1965
   struct _objc_symtab
1966
   {
1967
     long sel_ref_cnt;
1968
     SEL *refs;
1969
     short cls_def_cnt;
1970
     short cat_def_cnt;
1971
     void *defs[cls_def_cnt + cat_def_cnt];
1972
   }; */
1973
 
1974
static void
1975
build_objc_symtab_template (void)
1976
{
1977
  tree fields, array_type, *chain = NULL;
1978
  int index;
1979
 
1980
  objc_symtab_template = objc_start_struct (get_identifier (UTAG_SYMTAB));
1981
 
1982
  /* long sel_ref_cnt; */
1983
  fields = add_field_decl (long_integer_type_node, "sel_ref_cnt", &chain);
1984
 
1985
  /* SEL *refs; */
1986
  add_field_decl (build_pointer_type (objc_selector_type), "refs", &chain);
1987
 
1988
  /* short cls_def_cnt; */
1989
  add_field_decl (short_integer_type_node, "cls_def_cnt", &chain);
1990
 
1991
  /* short cat_def_cnt; */
1992
  add_field_decl (short_integer_type_node, "cat_def_cnt", &chain);
1993
 
1994
  /* Note that padding will be added here on LP64.  */
1995
 
1996
  /* void *defs[imp_count + cat_count (+ 1)]; */
1997
  /* NB: The index is one less than the size of the array.  */
1998
  index = imp_count + cat_count;
1999
  array_type = build_sized_array_type (ptr_type_node, index + 1);
2000
  add_field_decl (array_type, "defs", &chain);
2001
 
2002
  objc_finish_struct (objc_symtab_template, fields);
2003
}
2004
/* Construct the initial value for all of _objc_symtab.  */
2005
 
2006
static tree
2007
init_objc_symtab (tree type)
2008
{
2009
  tree field, expr, ltyp;
2010
  location_t loc;
2011
  VEC(constructor_elt,gc) *v = NULL;
2012
 
2013
  loc = UNKNOWN_LOCATION;
2014
 
2015
  /* sel_ref_cnt = { ..., 5, ... } */
2016
 
2017
  CONSTRUCTOR_APPEND_ELT (v, NULL_TREE,
2018
                          build_int_cst (long_integer_type_node, 0));
2019
 
2020
  /* refs = { ..., _OBJC_SELECTOR_TABLE, ... } */
2021
 
2022
  ltyp = build_pointer_type (objc_selector_type);
2023
  if (sel_ref_chain)
2024
    expr = convert (ltyp, build_unary_op (loc, ADDR_EXPR,
2025
                                          UOBJC_SELECTOR_TABLE_decl, 1));
2026
  else
2027
    expr = convert (ltyp, null_pointer_node);
2028
  CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
2029
 
2030
  /* cls_def_cnt = { ..., 5, ... } */
2031
 
2032
  CONSTRUCTOR_APPEND_ELT (v, NULL_TREE,
2033
                          build_int_cst (short_integer_type_node, imp_count));
2034
 
2035
  /* cat_def_cnt = { ..., 5, ... } */
2036
 
2037
  CONSTRUCTOR_APPEND_ELT (v, NULL_TREE,
2038
                          build_int_cst (short_integer_type_node, cat_count));
2039
 
2040
  /* cls_def = { ..., { &Foo, &Bar, ...}, ... } */
2041
 
2042
  field = TYPE_FIELDS (type);
2043
  field = DECL_CHAIN (DECL_CHAIN (DECL_CHAIN (DECL_CHAIN (field))));
2044
 
2045
  CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, init_def_list (TREE_TYPE (field)));
2046
 
2047
  return objc_build_constructor (type, v);
2048
}
2049
 
2050
/* Create the declaration of _OBJC_SYMBOLS, with type `struct _objc_symtab'
2051
   and initialized appropriately.  */
2052
 
2053
static void
2054
generate_objc_symtab_decl (void)
2055
{
2056
  build_objc_symtab_template ();
2057
  UOBJC_SYMBOLS_decl = start_var_decl (objc_symtab_template, "_OBJC_SYMBOLS");
2058
  OBJCMETA (UOBJC_SYMBOLS_decl, objc_meta, meta_base);
2059
  finish_var_decl (UOBJC_SYMBOLS_decl,
2060
                   init_objc_symtab (TREE_TYPE (UOBJC_SYMBOLS_decl)));
2061
}
2062
 
2063
static void
2064
objc_generate_v1_gnu_metadata (void)
2065
{
2066
  struct imp_entry *impent;
2067
  tree chain;
2068
 
2069
  /* Process the static instances here because initialization of objc_symtab
2070
     depends on them.  */
2071
  if (objc_static_instances)
2072
    generate_static_references ();
2073
 
2074
  objc_implementation_context =
2075
  implementation_template =
2076
  UOBJC_CLASS_decl =
2077
  UOBJC_METACLASS_decl = NULL_TREE;
2078
 
2079
  for (impent = imp_list; impent; impent = impent->next)
2080
    {
2081
      /* If -gen-decls is present, Dump the @interface of each class.
2082
         TODO: Dump the classes in the  order they were found, rather than in
2083
         reverse order as we are doing now.  */
2084
      if (flag_gen_declaration)
2085
        dump_interface (gen_declaration_file, impent->imp_context);
2086
 
2087
      /* all of the following reference the string pool...  */
2088
      if (TREE_CODE (impent->imp_context) == CLASS_IMPLEMENTATION_TYPE)
2089
        generate_class_structures (impent);
2090
      else
2091
        generate_category (impent);
2092
    }
2093
 
2094
  /* If we are using an array of selectors, we must always
2095
     finish up the array decl even if no selectors were used.  */
2096
  build_gnu_selector_translation_table ();
2097
 
2098
  if (protocol_chain)
2099
    generate_protocols ();
2100
 
2101
  /* Arrange for ObjC data structures to be initialized at run time.  */
2102
  /* FIXME: Have some more elegant way to determine if we need to
2103
     generate objc_symtab_decl or not, instead of checking these
2104
     global symbols.  */
2105
  if (imp_list || class_names_chain
2106
      || meth_var_names_chain || meth_var_types_chain || sel_ref_chain
2107
      || prop_names_attr_chain)
2108
    generate_objc_symtab_decl ();
2109
 
2110
  if (imp_list || class_names_chain || objc_static_instances
2111
      || meth_var_names_chain || meth_var_types_chain || sel_ref_chain)
2112
    {
2113
      /* Make sure that the meta-data are identified as being
2114
         GNU-runtime.  */
2115
      build_module_descriptor (OBJC_VERSION,
2116
                               build_tree_list (objc_meta, meta_base));
2117
      build_module_initializer_routine ();
2118
    }
2119
 
2120
  /* Dump the class references.  This forces the appropriate classes
2121
     to be linked into the executable image, preserving unix archive
2122
     semantics.  This can be removed when we move to a more dynamically
2123
     linked environment.  */
2124
 
2125
  for (chain = cls_ref_chain; chain; chain = TREE_CHAIN (chain))
2126
    {
2127
      handle_class_ref (chain);
2128
      if (TREE_PURPOSE (chain))
2129
        generate_classref_translation_entry (chain);
2130
    }
2131
 
2132
  for (impent = imp_list; impent; impent = impent->next)
2133
    handle_impent (impent);
2134
 
2135
  generate_strings ();
2136
}
2137
 
2138
/* --- exceptions --- */
2139
 
2140
static GTY(()) tree objc_eh_personality_decl;
2141
 
2142
static tree
2143
objc_eh_runtime_type (tree type)
2144
{
2145
  tree ident, eh_id, decl, str;
2146
 
2147
  if (type == error_mark_node
2148
      || errorcount || sorrycount)
2149
    {
2150
      /* Use 'ErrorMarkNode' as class name when error_mark_node is found
2151
         to prevent an ICE.  Note that we know that the compiler will
2152
         terminate with an error and this 'ErrorMarkNode' class name will
2153
         never be actually used.  */
2154
      ident = get_identifier ("ErrorMarkNode");
2155
      goto make_err_class;
2156
    }
2157
 
2158
  if (POINTER_TYPE_P (type) && objc_is_object_id (TREE_TYPE (type)))
2159
    /* We don't want to identify 'id' for GNU. Instead, build a 0
2160
       entry in the exceptions table.  */
2161
    return null_pointer_node;
2162
 
2163
  if (!POINTER_TYPE_P (type) || !TYPED_OBJECT (TREE_TYPE (type)))
2164
    {
2165
#ifdef OBJCPLUS
2166
      /* This routine is also called for c++ catch clauses; in which case,
2167
         we use the c++ typeinfo decl. */
2168
      return build_eh_type_type (type);
2169
#else
2170
      error ("non-objective-c type '%T' cannot be caught", type);
2171
      ident = get_identifier ("ErrorMarkNode");
2172
      goto make_err_class;
2173
#endif
2174
    }
2175
  else
2176
    ident = OBJC_TYPE_NAME (TREE_TYPE (type));
2177
 
2178
make_err_class:
2179
  /* If this class was already referenced, then it will be output during
2180
     meta-data emission, so we don't need to do it here.  */
2181
  decl = get_objc_string_decl (ident, class_names);
2182
  eh_id = add_objc_string (ident, class_names);
2183
  if (!decl)
2184
    {
2185
      /* Not found ... so we need to build it - from the freshly-entered id.  */
2186
      decl = get_objc_string_decl (ident, class_names);
2187
      str = my_build_string (IDENTIFIER_LENGTH (ident) + 1,
2188
                             IDENTIFIER_POINTER (ident));
2189
      /* We have to finalize this var here, because this might be called after
2190
         all the other metadata strings have been emitted.  */
2191
      finish_var_decl (decl, str);
2192
    }
2193
  return eh_id;
2194
}
2195
 
2196
static tree
2197
objc_eh_personality (void)
2198
{
2199
  if (!objc_eh_personality_decl)
2200
#ifndef OBJCPLUS
2201
    objc_eh_personality_decl = build_personality_function  ("gnu_objc");
2202
#else
2203
    objc_eh_personality_decl = build_personality_function  ("gxx");
2204
#endif
2205
  return objc_eh_personality_decl;
2206
}
2207
 
2208
/* -- interfaces --- */
2209
 
2210
static tree
2211
build_throw_stmt (location_t loc, tree throw_expr, bool rethrown ATTRIBUTE_UNUSED)
2212
{
2213
  tree t;
2214
  VEC(tree, gc) *parms = VEC_alloc (tree, gc, 1);
2215
  /* A throw is just a call to the runtime throw function with the
2216
     object as a parameter.  */
2217
  VEC_quick_push (tree, parms, throw_expr);
2218
  t = build_function_call_vec (loc, objc_exception_throw_decl, parms, NULL);
2219
  VEC_free (tree, gc, parms);
2220
  return add_stmt (t);
2221
}
2222
 
2223
/* Build __builtin_eh_pointer.  */
2224
 
2225
static tree
2226
objc_build_exc_ptr (struct objc_try_context **x ATTRIBUTE_UNUSED)
2227
{
2228
  tree t;
2229
  t = builtin_decl_explicit (BUILT_IN_EH_POINTER);
2230
  t = build_call_expr (t, 1, integer_zero_node);
2231
  return fold_convert (objc_object_type, t);
2232
}
2233
 
2234
static tree
2235
begin_catch (struct objc_try_context **cur_try_context, tree type,
2236
             tree decl, tree compound, bool ellipsis ATTRIBUTE_UNUSED)
2237
{
2238
  tree t;
2239
  /* Record the data for the catch in the try context so that we can
2240
     finalize it later.  */
2241
  if (ellipsis)
2242
    t = build_stmt (input_location, CATCH_EXPR, NULL, compound);
2243
  else
2244
    t = build_stmt (input_location, CATCH_EXPR, type, compound);
2245
  (*cur_try_context)->current_catch = t;
2246
 
2247
  /* Initialize the decl from the EXC_PTR_EXPR we get from the runtime.  */
2248
  t = objc_build_exc_ptr (cur_try_context);
2249
  t = convert (TREE_TYPE (decl), t);
2250
  return build2 (MODIFY_EXPR, void_type_node, decl, t);
2251
}
2252
 
2253
static void
2254
finish_catch (struct objc_try_context **cur_try_context, tree current_catch)
2255
{
2256
  append_to_statement_list (current_catch, &((*cur_try_context)->catch_list));
2257
}
2258
 
2259
static tree
2260
finish_try_stmt (struct objc_try_context **cur_try_context)
2261
{
2262
  struct objc_try_context *c = *cur_try_context;
2263
  tree stmt = c->try_body;
2264
  if (c->catch_list)
2265
    stmt = build_stmt (c->try_locus, TRY_CATCH_EXPR, stmt, c->catch_list);
2266
  if (c->finally_body)
2267
    stmt = build_stmt (c->try_locus, TRY_FINALLY_EXPR, stmt, c->finally_body);
2268
  return stmt;
2269
}
2270
 
2271
#include "gt-objc-objc-gnu-runtime-abi-01.h"

powered by: WebSVN 2.1.0

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