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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [gcc/] [objc/] [objc-encoding.c] - Blame information for rev 717

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 717 jeremybenn
/* Routines dealing with ObjC encoding of types
2
   Copyright (C) 1992, 1993, 1994, 1995, 1997, 1998, 1999, 2000, 2001,
3
   2002, 2003, 2004, 2005, 2007, 2008, 2009, 2010, 2011
4
   Free Software Foundation, Inc.
5
 
6
This file is part of GCC.
7
 
8
GCC is free software; you can redistribute it and/or modify
9
it under the terms of the GNU General Public License as published by
10
the Free Software Foundation; either version 3, or (at your option)
11
any later version.
12
 
13
GCC is distributed in the hope that it will be useful,
14
but WITHOUT ANY WARRANTY; without even the implied warranty of
15
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
GNU General Public License for more details.
17
 
18
You should have received a copy of the GNU General Public License
19
along with GCC; see the file COPYING3.  If not see
20
<http://www.gnu.org/licenses/>.  */
21
 
22
#include "config.h"
23
#include "system.h"
24
#include "coretypes.h"
25
#include "tree.h"
26
 
27
#ifdef OBJCPLUS
28
#include "cp-tree.h"
29
#else
30
#include "c-tree.h"
31
#include "c-lang.h"
32
#endif
33
 
34
#include "c-family/c-common.h"
35
#include "c-family/c-objc.h"
36
 
37
#include "objc-encoding.h"
38
#include "objc-act.h"
39
 
40
/* For my_build_string().  */
41
#include "objc-runtime-shared-support.h"
42
 
43
/* For BITS_PER_UNIT.  */
44
#include "tm.h"
45
 
46
/* When building Objective-C++, we are not linking against the C front-end
47
   and so need to replicate the C tree-construction functions in some way.  */
48
#ifdef OBJCPLUS
49
#define OBJCP_REMAP_FUNCTIONS
50
#include "objcp-decl.h"
51
#endif  /* OBJCPLUS */
52
 
53
/* Set up for use of obstacks.  */
54
#include "obstack.h"
55
 
56
/* This obstack is used to accumulate the encoding of a data type.  */
57
static struct obstack util_obstack;
58
 
59
/* This points to the beginning of obstack contents, so we can free
60
   the whole contents.  */
61
static char *util_firstobj;
62
 
63
void objc_encoding_init (void)
64
{
65
  gcc_obstack_init (&util_obstack);
66
  util_firstobj = (char *) obstack_finish (&util_obstack);
67
}
68
 
69
int generating_instance_variables = 0;
70
 
71
static void encode_type_qualifiers (tree);
72
static void encode_type (tree, int, int);
73
static void encode_field (tree field_decl, int curtype, int format);
74
 
75
static tree
76
objc_method_parm_type (tree type)
77
{
78
  type = TREE_VALUE (TREE_TYPE (type));
79
  if (TREE_CODE (type) == TYPE_DECL)
80
    type = TREE_TYPE (type);
81
  return type;
82
}
83
 
84
static int
85
objc_encoded_type_size (tree type)
86
{
87
  int sz = int_size_in_bytes (type);
88
 
89
  /* Make all integer and enum types at least as large
90
     as an int.  */
91
  if (sz > 0 && INTEGRAL_TYPE_P (type))
92
    sz = MAX (sz, int_size_in_bytes (integer_type_node));
93
  /* Treat arrays as pointers, since that's how they're
94
     passed in.  */
95
  else if (TREE_CODE (type) == ARRAY_TYPE)
96
    sz = int_size_in_bytes (ptr_type_node);
97
  return sz;
98
}
99
 
100
/* Encode a method prototype.  */
101
tree
102
encode_method_prototype (tree method_decl)
103
{
104
  tree parms;
105
  int parm_offset, i;
106
  char buf[40];
107
  tree result;
108
 
109
  /* ONEWAY and BYCOPY, for remote object are the only method qualifiers.  */
110
  encode_type_qualifiers (TREE_PURPOSE (TREE_TYPE (method_decl)));
111
 
112
  /* Encode return type.  */
113
  encode_type (objc_method_parm_type (method_decl),
114
               obstack_object_size (&util_obstack),
115
               OBJC_ENCODE_INLINE_DEFS);
116
 
117
  /* Stack size.  */
118
  /* The first two arguments (self and _cmd) are pointers; account for
119
     their size.  */
120
  i = int_size_in_bytes (ptr_type_node);
121
  parm_offset = 2 * i;
122
  for (parms = METHOD_SEL_ARGS (method_decl); parms;
123
       parms = DECL_CHAIN (parms))
124
    {
125
      tree type = objc_method_parm_type (parms);
126
      int sz = objc_encoded_type_size (type);
127
 
128
      /* If a type size is not known, bail out.  */
129
      if (sz < 0)
130
        {
131
          error_at (DECL_SOURCE_LOCATION (method_decl),
132
                    "type %qT does not have a known size",
133
                    type);
134
          /* Pretend that the encoding succeeded; the compilation will
135
             fail nevertheless.  */
136
          goto finish_encoding;
137
        }
138
      parm_offset += sz;
139
    }
140
 
141
  sprintf (buf, "%d@0:%d", parm_offset, i);
142
  obstack_grow (&util_obstack, buf, strlen (buf));
143
 
144
  /* Argument types.  */
145
  parm_offset = 2 * i;
146
  for (parms = METHOD_SEL_ARGS (method_decl); parms;
147
       parms = DECL_CHAIN (parms))
148
    {
149
      tree type = objc_method_parm_type (parms);
150
 
151
      /* Process argument qualifiers for user supplied arguments.  */
152
      encode_type_qualifiers (TREE_PURPOSE (TREE_TYPE (parms)));
153
 
154
      /* Type.  */
155
      encode_type (type, obstack_object_size (&util_obstack),
156
                   OBJC_ENCODE_INLINE_DEFS);
157
 
158
      /* Compute offset.  */
159
      sprintf (buf, "%d", parm_offset);
160
      parm_offset += objc_encoded_type_size (type);
161
 
162
      obstack_grow (&util_obstack, buf, strlen (buf));
163
    }
164
 
165
  finish_encoding:
166
  obstack_1grow (&util_obstack, '\0');
167
  result = get_identifier (XOBFINISH (&util_obstack, char *));
168
  obstack_free (&util_obstack, util_firstobj);
169
  return result;
170
}
171
 
172
/* This is used to implement @encode().  */
173
tree
174
objc_build_encode_expr (tree type)
175
{
176
  tree result;
177
  const char *string;
178
 
179
  encode_type (type, obstack_object_size (&util_obstack),
180
               OBJC_ENCODE_INLINE_DEFS);
181
  obstack_1grow (&util_obstack, 0);    /* null terminate string */
182
  string = XOBFINISH (&util_obstack, const char *);
183
 
184
  /* Synthesize a string that represents the encoded struct/union.  */
185
  result = my_build_string (strlen (string) + 1, string);
186
  obstack_free (&util_obstack, util_firstobj);
187
  return result;
188
}
189
 
190
/* "Encode" a data type into a string, which grows in util_obstack.
191
 
192
   The format is described in gcc/doc/objc.texi, section 'Type
193
   encoding'.
194
 
195
   Most of the encode_xxx functions have a 'type' argument, which is
196
   the type to encode, and an integer 'curtype' argument, which is the
197
   index in the encoding string of the beginning of the encoding of
198
   the current type, and allows you to find what characters have
199
   already been written for the current type (they are the ones in the
200
   current encoding string starting from 'curtype').
201
 
202
   For example, if we are encoding a method which returns 'int' and
203
   takes a 'char **' argument, then when we get to the point of
204
   encoding the 'char **' argument, the encoded string already
205
   contains 'i12@0:4' (assuming a pointer size of 4 bytes).  So,
206
   'curtype' will be set to 7 when starting to encode 'char **'.
207
   During the whole of the encoding of 'char **', 'curtype' will be
208
   fixed at 7, so the routine encoding the second pointer can find out
209
   that it's actually encoding a pointer to a pointer by looking
210
   backwards at what has already been encoded for the current type,
211
   and seeing there is a "^" (meaning a pointer) in there.  */
212
 
213
 
214
/* Encode type qualifiers encodes one of the "PQ" Objective-C
215
   keywords, ie 'in', 'out', 'inout', 'bycopy', 'byref', 'oneway'.
216
   'const', instead, is encoded directly as part of the type.  */
217
static void
218
encode_type_qualifiers (tree declspecs)
219
{
220
  tree spec;
221
 
222
  for (spec = declspecs; spec; spec = TREE_CHAIN (spec))
223
    {
224
      /* FIXME: Shouldn't we use token->keyword here ? */
225
      if (ridpointers[(int) RID_IN] == TREE_VALUE (spec))
226
        obstack_1grow (&util_obstack, 'n');
227
      else if (ridpointers[(int) RID_INOUT] == TREE_VALUE (spec))
228
        obstack_1grow (&util_obstack, 'N');
229
      else if (ridpointers[(int) RID_OUT] == TREE_VALUE (spec))
230
        obstack_1grow (&util_obstack, 'o');
231
      else if (ridpointers[(int) RID_BYCOPY] == TREE_VALUE (spec))
232
        obstack_1grow (&util_obstack, 'O');
233
      else if (ridpointers[(int) RID_BYREF] == TREE_VALUE (spec))
234
        obstack_1grow (&util_obstack, 'R');
235
      else if (ridpointers[(int) RID_ONEWAY] == TREE_VALUE (spec))
236
        obstack_1grow (&util_obstack, 'V');
237
      else
238
        gcc_unreachable ();
239
    }
240
}
241
 
242
/* Determine if a pointee is marked read-only.  Only used by the NeXT
243
   runtime to be compatible with gcc-3.3.  */
244
static bool
245
pointee_is_readonly (tree pointee)
246
{
247
  while (POINTER_TYPE_P (pointee))
248
    pointee = TREE_TYPE (pointee);
249
 
250
  return TYPE_READONLY (pointee);
251
}
252
 
253
/* Encode a pointer type.  */
254
static void
255
encode_pointer (tree type, int curtype, int format)
256
{
257
  tree pointer_to = TREE_TYPE (type);
258
 
259
  if (flag_next_runtime)
260
    {
261
      /* This code is used to be compatible with gcc-3.3.  */
262
      /* For historical/compatibility reasons, the read-only qualifier
263
         of the pointee gets emitted _before_ the '^'.  The read-only
264
         qualifier of the pointer itself gets ignored, _unless_ we are
265
         looking at a typedef!  Also, do not emit the 'r' for anything
266
         but the outermost type!  */
267
      if (!generating_instance_variables
268
          && (obstack_object_size (&util_obstack) - curtype <= 1)
269
          && (TYPE_NAME (type) && TREE_CODE (TYPE_NAME (type)) == TYPE_DECL
270
              ? TYPE_READONLY (type)
271
              : pointee_is_readonly (pointer_to)))
272
        obstack_1grow (&util_obstack, 'r');
273
    }
274
 
275
  if (TREE_CODE (pointer_to) == RECORD_TYPE)
276
    {
277
      if (OBJC_TYPE_NAME (pointer_to)
278
          && TREE_CODE (OBJC_TYPE_NAME (pointer_to)) == IDENTIFIER_NODE)
279
        {
280
          const char *name = IDENTIFIER_POINTER (OBJC_TYPE_NAME (pointer_to));
281
 
282
          if (strcmp (name, TAG_OBJECT) == 0) /* '@' */
283
            {
284
              obstack_1grow (&util_obstack, '@');
285
              return;
286
            }
287
          else if (TYPE_HAS_OBJC_INFO (pointer_to)
288
                   && TYPE_OBJC_INTERFACE (pointer_to))
289
            {
290
              if (generating_instance_variables)
291
                {
292
                  obstack_1grow (&util_obstack, '@');
293
                  obstack_1grow (&util_obstack, '"');
294
                  obstack_grow (&util_obstack, name, strlen (name));
295
                  obstack_1grow (&util_obstack, '"');
296
                  return;
297
                }
298
              else
299
                {
300
                  obstack_1grow (&util_obstack, '@');
301
                  return;
302
                }
303
            }
304
          else if (strcmp (name, TAG_CLASS) == 0) /* '#' */
305
            {
306
              obstack_1grow (&util_obstack, '#');
307
              return;
308
            }
309
          else if (strcmp (name, TAG_SELECTOR) == 0) /* ':' */
310
            {
311
              obstack_1grow (&util_obstack, ':');
312
              return;
313
            }
314
        }
315
    }
316
  else if (TREE_CODE (pointer_to) == INTEGER_TYPE
317
           && TYPE_MODE (pointer_to) == QImode)
318
    {
319
      tree pname = TREE_CODE (OBJC_TYPE_NAME (pointer_to)) == IDENTIFIER_NODE
320
                  ? OBJC_TYPE_NAME (pointer_to)
321
                  : DECL_NAME (OBJC_TYPE_NAME (pointer_to));
322
 
323
      /* (BOOL *) are an exception and are encoded as ^c, while all
324
         other pointers to char are encoded as *.   */
325
      if (strcmp (IDENTIFIER_POINTER (pname), "BOOL"))
326
        {
327
          if (!flag_next_runtime)
328
            {
329
              /* The NeXT runtime adds the 'r' before getting here.  */
330
 
331
              /* It appears that "r*" means "const char *" rather than
332
                 "char *const".  "char *const" is encoded as "*",
333
                 which is identical to "char *", so the "const" is
334
                 unfortunately lost.  */
335
              if (TYPE_READONLY (pointer_to))
336
                obstack_1grow (&util_obstack, 'r');
337
            }
338
 
339
          obstack_1grow (&util_obstack, '*');
340
          return;
341
        }
342
    }
343
 
344
  /* We have a normal pointer type that does not get special treatment.  */
345
  obstack_1grow (&util_obstack, '^');
346
  encode_type (pointer_to, curtype, format);
347
}
348
 
349
static void
350
encode_array (tree type, int curtype, int format)
351
{
352
  tree an_int_cst = TYPE_SIZE (type);
353
  tree array_of = TREE_TYPE (type);
354
  char buffer[40];
355
 
356
  if (an_int_cst == NULL)
357
    {
358
      /* We are trying to encode an incomplete array.  An incomplete
359
         array is forbidden as part of an instance variable; but it
360
         may occur if the instance variable is a pointer to such an
361
         array.  */
362
 
363
      /* So the only case in which an incomplete array could occur
364
         (without being pointed to) is if we are encoding the
365
         arguments or return value of a method.  In that case, an
366
         incomplete array argument or return value (eg,
367
         -(void)display: (char[])string) is treated like a pointer
368
         because that is how the compiler does the function call.  A
369
         special, more complicated case, is when the incomplete array
370
         is the last member of a struct (eg, if we are encoding
371
         "struct { unsigned long int a;double b[];}"), which is again
372
         part of a method argument/return value.  In that case, we
373
         really need to communicate to the runtime that there is an
374
         incomplete array (not a pointer!) there.  So, we detect that
375
         special case and encode it as a zero-length array.
376
 
377
         Try to detect that we are part of a struct.  We do this by
378
         searching for '=' in the type encoding for the current type.
379
         NB: This hack assumes that you can't use '=' as part of a C
380
         identifier.
381
      */
382
      {
383
        char *enc = obstack_base (&util_obstack) + curtype;
384
        if (memchr (enc, '=',
385
                    obstack_object_size (&util_obstack) - curtype) == NULL)
386
          {
387
            /* We are not inside a struct.  Encode the array as a
388
               pointer.  */
389
            encode_pointer (type, curtype, format);
390
            return;
391
          }
392
      }
393
 
394
      /* Else, we are in a struct, and we encode it as a zero-length
395
         array.  */
396
      sprintf (buffer, "[" HOST_WIDE_INT_PRINT_DEC, (HOST_WIDE_INT)0);
397
    }
398
  else if (TREE_INT_CST_LOW (TYPE_SIZE (array_of)) == 0)
399
   sprintf (buffer, "[" HOST_WIDE_INT_PRINT_DEC, (HOST_WIDE_INT)0);
400
  else
401
    sprintf (buffer, "[" HOST_WIDE_INT_PRINT_DEC,
402
             TREE_INT_CST_LOW (an_int_cst)
403
              / TREE_INT_CST_LOW (TYPE_SIZE (array_of)));
404
 
405
  obstack_grow (&util_obstack, buffer, strlen (buffer));
406
  encode_type (array_of, curtype, format);
407
  obstack_1grow (&util_obstack, ']');
408
  return;
409
}
410
 
411
/* Encode a vector.  The vector type is a GCC extension to C.  */
412
static void
413
encode_vector (tree type, int curtype, int format)
414
{
415
  tree vector_of = TREE_TYPE (type);
416
  char buffer[40];
417
 
418
  /* Vectors are like simple fixed-size arrays.  */
419
 
420
  /* Output ![xx,yy,<code>] where xx is the vector_size, yy is the
421
     alignment of the vector, and <code> is the base type.  Eg, int
422
     __attribute__ ((vector_size (16))) gets encoded as ![16,32,i]
423
     assuming that the alignment is 32 bytes.  We include size and
424
     alignment in bytes so that the runtime does not have to have any
425
     knowledge of the actual types.
426
  */
427
  sprintf (buffer, "![" HOST_WIDE_INT_PRINT_DEC ",%d",
428
           /* We want to compute the equivalent of sizeof (<vector>).
429
              Code inspired by c_sizeof_or_alignof_type.  */
430
           ((TREE_INT_CST_LOW (TYPE_SIZE_UNIT (type))
431
             / (TYPE_PRECISION (char_type_node) / BITS_PER_UNIT))),
432
           /* We want to compute the equivalent of __alignof__
433
              (<vector>).  Code inspired by
434
              c_sizeof_or_alignof_type.  */
435
           TYPE_ALIGN_UNIT (type));
436
  obstack_grow (&util_obstack, buffer, strlen (buffer));
437
  encode_type (vector_of, curtype, format);
438
  obstack_1grow (&util_obstack, ']');
439
  return;
440
}
441
 
442
static void
443
encode_aggregate_fields (tree type, bool pointed_to, int curtype, int format)
444
{
445
  tree field = TYPE_FIELDS (type);
446
 
447
  for (; field; field = DECL_CHAIN (field))
448
    {
449
#ifdef OBJCPLUS
450
      /* C++ static members, and things that are not field at all,
451
         should not appear in the encoding.  */
452
      if (TREE_CODE (field) != FIELD_DECL || TREE_STATIC (field))
453
        continue;
454
#endif
455
 
456
      /* Recursively encode fields of embedded base classes.  */
457
      if (DECL_ARTIFICIAL (field) && !DECL_NAME (field)
458
          && TREE_CODE (TREE_TYPE (field)) == RECORD_TYPE)
459
        {
460
          encode_aggregate_fields (TREE_TYPE (field),
461
                                   pointed_to, curtype, format);
462
          continue;
463
        }
464
 
465
      if (generating_instance_variables && !pointed_to)
466
        {
467
          tree fname = DECL_NAME (field);
468
 
469
          obstack_1grow (&util_obstack, '"');
470
 
471
          if (fname && TREE_CODE (fname) == IDENTIFIER_NODE)
472
            obstack_grow (&util_obstack,
473
                          IDENTIFIER_POINTER (fname),
474
                          strlen (IDENTIFIER_POINTER (fname)));
475
 
476
          obstack_1grow (&util_obstack, '"');
477
        }
478
 
479
      encode_field (field, curtype, format);
480
    }
481
}
482
 
483
static void
484
encode_aggregate_within (tree type, int curtype, int format, int left,
485
                         int right)
486
{
487
  tree name;
488
  /* NB: aggregates that are pointed to have slightly different encoding
489
     rules in that you never encode the names of instance variables.  */
490
  int ob_size = obstack_object_size (&util_obstack);
491
  bool inline_contents = false;
492
  bool pointed_to = false;
493
 
494
  if (flag_next_runtime)
495
    {
496
      if (ob_size > 0  &&  *(obstack_next_free (&util_obstack) - 1) == '^')
497
        pointed_to = true;
498
 
499
      if ((format == OBJC_ENCODE_INLINE_DEFS || generating_instance_variables)
500
          && (!pointed_to || ob_size - curtype == 1
501
              || (ob_size - curtype == 2
502
                  && *(obstack_next_free (&util_obstack) - 2) == 'r')))
503
        inline_contents = true;
504
    }
505
  else
506
    {
507
      /* c0 and c1 are the last two characters in the encoding of the
508
         current type; if the last two characters were '^' or '^r',
509
         then we are encoding an aggregate that is "pointed to".  The
510
         comment above applies: in that case we should avoid encoding
511
         the names of instance variables.
512
      */
513
      char c1 = ob_size > 1 ? *(obstack_next_free (&util_obstack) - 2) : 0;
514
      char c0 = ob_size > 0 ? *(obstack_next_free (&util_obstack) - 1) : 0;
515
 
516
      if (c0 == '^' || (c1 == '^' && c0 == 'r'))
517
        pointed_to = true;
518
 
519
      if (format == OBJC_ENCODE_INLINE_DEFS || generating_instance_variables)
520
        {
521
          if (!pointed_to)
522
            inline_contents = true;
523
          else
524
            {
525
              /* Note that the check (ob_size - curtype < 2) prevents
526
                 infinite recursion when encoding a structure which is
527
                 a linked list (eg, struct node { struct node *next;
528
                 }).  Each time we follow a pointer, we add one
529
                 character to ob_size, and curtype is fixed, so after
530
                 at most two pointers we stop inlining contents and
531
                 break the loop.
532
 
533
                 The other case where we don't inline is "^r", which
534
                 is a pointer to a constant struct.
535
              */
536
              if ((ob_size - curtype <= 2) && !(c0 == 'r'))
537
                inline_contents = true;
538
            }
539
        }
540
    }
541
 
542
  /* Traverse struct aliases; it is important to get the
543
     original struct and its tag name (if any).  */
544
  type = TYPE_MAIN_VARIANT (type);
545
  name = OBJC_TYPE_NAME (type);
546
  /* Open parenth/bracket.  */
547
  obstack_1grow (&util_obstack, left);
548
 
549
  /* Encode the struct/union tag name, or '?' if a tag was
550
     not provided.  Typedef aliases do not qualify.  */
551
#ifdef OBJCPLUS
552
  /* For compatibility with the NeXT runtime, ObjC++ encodes template
553
     args as a composite struct tag name. */
554
  if (name && TREE_CODE (name) == IDENTIFIER_NODE
555
      /* Did this struct have a tag?  */
556
      && !TYPE_WAS_ANONYMOUS (type))
557
    obstack_grow (&util_obstack,
558
                  decl_as_string (type, TFF_DECL_SPECIFIERS | TFF_UNQUALIFIED_NAME),
559
                  strlen (decl_as_string (type, TFF_DECL_SPECIFIERS | TFF_UNQUALIFIED_NAME)));
560
#else
561
  if (name && TREE_CODE (name) == IDENTIFIER_NODE)
562
    obstack_grow (&util_obstack,
563
                  IDENTIFIER_POINTER (name),
564
                  strlen (IDENTIFIER_POINTER (name)));
565
#endif
566
  else
567
    obstack_1grow (&util_obstack, '?');
568
 
569
  /* Encode the types (and possibly names) of the inner fields,
570
     if required.  */
571
  if (inline_contents)
572
    {
573
      obstack_1grow (&util_obstack, '=');
574
      encode_aggregate_fields (type, pointed_to, curtype, format);
575
    }
576
  /* Close parenth/bracket.  */
577
  obstack_1grow (&util_obstack, right);
578
}
579
 
580
/* Encode a bitfield NeXT-style (i.e., without a bit offset or the underlying
581
   field type.  */
582
static void
583
encode_next_bitfield (int width)
584
{
585
  char buffer[40];
586
  sprintf (buffer, "b%d", width);
587
  obstack_grow (&util_obstack, buffer, strlen (buffer));
588
}
589
 
590
/* Encodes 'type', ignoring type qualifiers (which you should encode
591
   beforehand if needed) with the exception of 'const', which is
592
   encoded by encode_type.  See above for the explanation of
593
   'curtype'.  'format' can be OBJC_ENCODE_INLINE_DEFS or
594
   OBJC_ENCODE_DONT_INLINE_DEFS.  */
595
static void
596
encode_type (tree type, int curtype, int format)
597
{
598
  enum tree_code code = TREE_CODE (type);
599
 
600
  /* Ignore type qualifiers other than 'const' when encoding a
601
     type.  */
602
 
603
  if (type == error_mark_node)
604
    return;
605
 
606
  if (!flag_next_runtime)
607
    {
608
      if (TYPE_READONLY (type))
609
        obstack_1grow (&util_obstack, 'r');
610
    }
611
 
612
  switch (code)
613
    {
614
    case ENUMERAL_TYPE:
615
      if (flag_next_runtime)
616
        {
617
          /* Kludge for backwards-compatibility with gcc-3.3: enums
618
             are always encoded as 'i' no matter what type they
619
             actually are (!).  */
620
          obstack_1grow (&util_obstack, 'i');
621
          break;
622
        }
623
      /* Else, they are encoded exactly like the integer type that is
624
         used by the compiler to store them.  */
625
    case INTEGER_TYPE:
626
      {
627
        char c;
628
        switch (GET_MODE_BITSIZE (TYPE_MODE (type)))
629
          {
630
          case 8:  c = TYPE_UNSIGNED (type) ? 'C' : 'c'; break;
631
          case 16: c = TYPE_UNSIGNED (type) ? 'S' : 's'; break;
632
          case 32:
633
            {
634
              tree int_type = type;
635
              if (flag_next_runtime)
636
                {
637
                  /* Another legacy kludge for compatiblity with
638
                     gcc-3.3: 32-bit longs are encoded as 'l' or 'L',
639
                     but not always.  For typedefs, we need to use 'i'
640
                     or 'I' instead if encoding a struct field, or a
641
                     pointer!  */
642
                  int_type =  ((!generating_instance_variables
643
                                && (obstack_object_size (&util_obstack)
644
                                    == (unsigned) curtype))
645
                               ? TYPE_MAIN_VARIANT (type)
646
                               : type);
647
                }
648
              if (int_type == long_unsigned_type_node
649
                  || int_type == long_integer_type_node)
650
                c = TYPE_UNSIGNED (type) ? 'L' : 'l';
651
              else
652
                c = TYPE_UNSIGNED (type) ? 'I' : 'i';
653
            }
654
            break;
655
          case 64:  c = TYPE_UNSIGNED (type) ? 'Q' : 'q'; break;
656
          case 128: c = TYPE_UNSIGNED (type) ? 'T' : 't'; break;
657
          default: gcc_unreachable ();
658
          }
659
        obstack_1grow (&util_obstack, c);
660
        break;
661
      }
662
    case REAL_TYPE:
663
      {
664
        char c;
665
        /* Floating point types.  */
666
        switch (GET_MODE_BITSIZE (TYPE_MODE (type)))
667
          {
668
          case 32:  c = 'f'; break;
669
          case 64:  c = 'd'; break;
670
          case 96:
671
          case 128: c = 'D'; break;
672
          default: gcc_unreachable ();
673
          }
674
        obstack_1grow (&util_obstack, c);
675
        break;
676
      }
677
    case VOID_TYPE:
678
      obstack_1grow (&util_obstack, 'v');
679
      break;
680
 
681
    case BOOLEAN_TYPE:
682
      obstack_1grow (&util_obstack, 'B');
683
      break;
684
 
685
    case ARRAY_TYPE:
686
      encode_array (type, curtype, format);
687
      break;
688
 
689
    case POINTER_TYPE:
690
#ifdef OBJCPLUS
691
    case REFERENCE_TYPE:
692
#endif
693
      encode_pointer (type, curtype, format);
694
      break;
695
 
696
    case RECORD_TYPE:
697
      encode_aggregate_within (type, curtype, format, '{', '}');
698
      break;
699
 
700
    case UNION_TYPE:
701
      encode_aggregate_within (type, curtype, format, '(', ')');
702
      break;
703
 
704
    case FUNCTION_TYPE: /* '?' means an unknown type.  */
705
      obstack_1grow (&util_obstack, '?');
706
      break;
707
 
708
    case COMPLEX_TYPE:
709
      /* A complex is encoded as 'j' followed by the inner type (eg,
710
         "_Complex int" is encoded as 'ji').  */
711
      obstack_1grow (&util_obstack, 'j');
712
      encode_type (TREE_TYPE (type), curtype, format);
713
      break;
714
 
715
    case VECTOR_TYPE:
716
      encode_vector (type, curtype, format);
717
      break;
718
 
719
    default:
720
      warning (0, "unknown type %<%T%> found during Objective-C encoding",
721
               TREE_TYPE (type));
722
      obstack_1grow (&util_obstack, '?');
723
      break;
724
    }
725
 
726
  if (flag_next_runtime)
727
    {
728
      /* Super-kludge.  Some ObjC qualifier and type combinations need
729
         to be rearranged for compatibility with gcc-3.3.  */
730
      if (code == POINTER_TYPE && obstack_object_size (&util_obstack) >= 3)
731
        {
732
          char *enc = obstack_base (&util_obstack) + curtype;
733
 
734
          /* Rewrite "in const" from "nr" to "rn".  */
735
          if (curtype >= 1 && !strncmp (enc - 1, "nr", 2))
736
            strncpy (enc - 1, "rn", 2);
737
        }
738
    }
739
}
740
 
741
static void
742
encode_gnu_bitfield (int position, tree type, int size)
743
{
744
  enum tree_code code = TREE_CODE (type);
745
  char buffer[40];
746
  char charType = '?';
747
 
748
  /* This code is only executed for the GNU runtime, so we can ignore
749
     the NeXT runtime kludge of always encoding enums as 'i' no matter
750
     what integers they actually are.  */
751
  if (code == INTEGER_TYPE  ||  code == ENUMERAL_TYPE)
752
    {
753
      if (integer_zerop (TYPE_MIN_VALUE (type)))
754
        /* Unsigned integer types.  */
755
        {
756
          switch (TYPE_MODE (type))
757
            {
758
            case QImode:
759
              charType = 'C'; break;
760
            case HImode:
761
              charType = 'S'; break;
762
            case SImode:
763
              {
764
                if (type == long_unsigned_type_node)
765
                  charType = 'L';
766
                else
767
                  charType = 'I';
768
                break;
769
              }
770
            case DImode:
771
              charType = 'Q'; break;
772
            default:
773
              gcc_unreachable ();
774
            }
775
        }
776
      else
777
        /* Signed integer types.  */
778
        {
779
          switch (TYPE_MODE (type))
780
            {
781
            case QImode:
782
              charType = 'c'; break;
783
            case HImode:
784
              charType = 's'; break;
785
            case SImode:
786
              {
787
                if (type == long_integer_type_node)
788
                  charType = 'l';
789
                else
790
                  charType = 'i';
791
                break;
792
              }
793
            case DImode:
794
              charType = 'q'; break;
795
            default:
796
              gcc_unreachable ();
797
            }
798
        }
799
    }
800
  else
801
    {
802
      /* Do not do any encoding, produce an error and keep going.  */
803
      error ("trying to encode non-integer type as a bitfield");
804
      return;
805
    }
806
 
807
  sprintf (buffer, "b%d%c%d", position, charType, size);
808
  obstack_grow (&util_obstack, buffer, strlen (buffer));
809
}
810
 
811
static void
812
encode_field (tree field_decl, int curtype, int format)
813
{
814
#ifdef OBJCPLUS
815
  /* C++ static members, and things that are not fields at all,
816
     should not appear in the encoding.  */
817
  if (TREE_CODE (field_decl) != FIELD_DECL || TREE_STATIC (field_decl))
818
    return;
819
#endif
820
 
821
  /* Generate the bitfield typing information, if needed.  Note the difference
822
     between GNU and NeXT runtimes.  */
823
  if (DECL_BIT_FIELD_TYPE (field_decl))
824
    {
825
      int size = tree_low_cst (DECL_SIZE (field_decl), 1);
826
 
827
      if (flag_next_runtime)
828
        encode_next_bitfield (size);
829
      else
830
        encode_gnu_bitfield (int_bit_position (field_decl),
831
                             DECL_BIT_FIELD_TYPE (field_decl), size);
832
    }
833
  else
834
    encode_type (TREE_TYPE (field_decl), curtype, format);
835
}
836
 
837
tree
838
encode_field_decl (tree field_decl)
839
{
840
  tree result;
841
 
842
  encode_field (field_decl,
843
                obstack_object_size (&util_obstack),
844
                OBJC_ENCODE_DONT_INLINE_DEFS);
845
 
846
  /* Null terminate string.  */
847
  obstack_1grow (&util_obstack, 0);
848
 
849
  /* Get identifier for the string.  */
850
  result = get_identifier (XOBFINISH (&util_obstack, char *));
851
  obstack_free (&util_obstack, util_firstobj);
852
 
853
  return result;
854
}
855
 
856
/* This routine encodes the attribute of the input PROPERTY according
857
   to following formula:
858
 
859
   Property attributes are stored as a comma-delimited C string.
860
   Simple attributes such as readonly are encoded as single
861
   character. The parametrized attributes, getter=name and
862
   setter=name, are encoded as a single character followed by an
863
   identifier.  Property types are also encoded as a parametrized
864
   attribute.  The characters used to encode these attributes are
865
   defined by the following enumeration:
866
 
867
   enum PropertyAttributes {
868
     kPropertyReadOnly = 'R',
869
     kPropertyBycopy = 'C',
870
     kPropertyByref = '&',
871
     kPropertyDynamic = 'D',
872
     kPropertyGetter = 'G',
873
     kPropertySetter = 'S',
874
     kPropertyInstanceVariable = 'V',
875
     kPropertyType = 'T',
876
     kPropertyWeak = 'W',
877
     kPropertyStrong = 'P',
878
     kPropertyNonAtomic = 'N'
879
   };  */
880
tree
881
objc_v2_encode_prop_attr (tree property)
882
{
883
  const char *string;
884
  tree type = TREE_TYPE (property);
885
 
886
  obstack_1grow (&util_obstack, 'T');
887
  encode_type (type, obstack_object_size (&util_obstack),
888
               OBJC_ENCODE_INLINE_DEFS);
889
 
890
  if (PROPERTY_READONLY (property))
891
    obstack_grow (&util_obstack, ",R", 2);
892
 
893
  switch (PROPERTY_ASSIGN_SEMANTICS (property))
894
    {
895
    case OBJC_PROPERTY_COPY:
896
      obstack_grow (&util_obstack, ",C", 2);
897
      break;
898
    case OBJC_PROPERTY_RETAIN:
899
      obstack_grow (&util_obstack, ",&", 2);
900
      break;
901
    case OBJC_PROPERTY_ASSIGN:
902
    default:
903
      break;
904
    }
905
 
906
  if (PROPERTY_DYNAMIC (property))
907
    obstack_grow (&util_obstack, ",D", 2);
908
 
909
  if (PROPERTY_NONATOMIC (property))
910
    obstack_grow (&util_obstack, ",N", 2);
911
 
912
  /* Here we want to encode the getter name, but only if it's not the
913
     standard one.  */
914
  if (PROPERTY_GETTER_NAME (property) != PROPERTY_NAME (property))
915
    {
916
      obstack_grow (&util_obstack, ",G", 2);
917
      string = IDENTIFIER_POINTER (PROPERTY_GETTER_NAME (property));
918
      obstack_grow (&util_obstack, string, strlen (string));
919
    }
920
 
921
  if (!PROPERTY_READONLY (property))
922
    {
923
      /* Here we want to encode the setter name, but only if it's not
924
         the standard one.  */
925
      tree standard_setter = get_identifier (objc_build_property_setter_name (PROPERTY_NAME (property)));
926
      if (PROPERTY_SETTER_NAME (property) != standard_setter)
927
        {
928
          obstack_grow (&util_obstack, ",S", 2);
929
          string = IDENTIFIER_POINTER (PROPERTY_SETTER_NAME (property));
930
          obstack_grow (&util_obstack, string, strlen (string));
931
        }
932
    }
933
 
934
  /* TODO: Encode strong ('P'), weak ('W') for garbage collection.  */
935
 
936
  if (!PROPERTY_DYNAMIC (property))
937
    {
938
      obstack_grow (&util_obstack, ",V", 2);
939
      if (PROPERTY_IVAR_NAME (property))
940
        string = IDENTIFIER_POINTER (PROPERTY_IVAR_NAME (property));
941
      else
942
        string = IDENTIFIER_POINTER (PROPERTY_NAME (property));
943
      obstack_grow (&util_obstack, string, strlen (string));
944
    }
945
 
946
  /* NULL-terminate string.  */
947
  obstack_1grow (&util_obstack, 0);
948
  string = XOBFINISH (&util_obstack, char *);
949
  obstack_free (&util_obstack, util_firstobj);
950
  return get_identifier (string);
951
}

powered by: WebSVN 2.1.0

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