136ac495dSmrg /* Routines dealing with ObjC encoding of types
2*8feb0f0bSmrg Copyright (C) 1992-2020 Free Software Foundation, Inc.
336ac495dSmrg
436ac495dSmrg This file is part of GCC.
536ac495dSmrg
636ac495dSmrg GCC is free software; you can redistribute it and/or modify
736ac495dSmrg it under the terms of the GNU General Public License as published by
836ac495dSmrg the Free Software Foundation; either version 3, or (at your option)
936ac495dSmrg any later version.
1036ac495dSmrg
1136ac495dSmrg GCC is distributed in the hope that it will be useful,
1236ac495dSmrg but WITHOUT ANY WARRANTY; without even the implied warranty of
1336ac495dSmrg MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1436ac495dSmrg GNU General Public License for more details.
1536ac495dSmrg
1636ac495dSmrg You should have received a copy of the GNU General Public License
1736ac495dSmrg along with GCC; see the file COPYING3. If not see
1836ac495dSmrg <http://www.gnu.org/licenses/>. */
1936ac495dSmrg
2036ac495dSmrg #include "config.h"
2136ac495dSmrg #include "system.h"
2236ac495dSmrg #include "coretypes.h"
2336ac495dSmrg #include "tree.h"
2436ac495dSmrg #include "options.h"
2536ac495dSmrg #include "stringpool.h"
2636ac495dSmrg #include "stor-layout.h"
2736ac495dSmrg
2836ac495dSmrg #ifdef OBJCPLUS
2936ac495dSmrg #include "cp/cp-tree.h"
3036ac495dSmrg #else
3136ac495dSmrg #include "c/c-tree.h"
3236ac495dSmrg #include "c/c-lang.h"
3336ac495dSmrg #endif
3436ac495dSmrg
3536ac495dSmrg #include "c-family/c-objc.h"
3636ac495dSmrg
3736ac495dSmrg #include "objc-encoding.h"
3836ac495dSmrg #include "objc-act.h"
3936ac495dSmrg
4036ac495dSmrg /* For my_build_string(). */
4136ac495dSmrg #include "objc-runtime-shared-support.h"
4236ac495dSmrg
4336ac495dSmrg /* For BITS_PER_UNIT. */
4436ac495dSmrg
4536ac495dSmrg /* When building Objective-C++, we are not linking against the C front-end
4636ac495dSmrg and so need to replicate the C tree-construction functions in some way. */
4736ac495dSmrg #ifdef OBJCPLUS
4836ac495dSmrg #define OBJCP_REMAP_FUNCTIONS
4936ac495dSmrg #include "objcp-decl.h"
5036ac495dSmrg #endif /* OBJCPLUS */
5136ac495dSmrg
5236ac495dSmrg /* Set up for use of obstacks. */
5336ac495dSmrg
5436ac495dSmrg /* This obstack is used to accumulate the encoding of a data type. */
5536ac495dSmrg static struct obstack util_obstack;
5636ac495dSmrg
5736ac495dSmrg /* This points to the beginning of obstack contents, so we can free
5836ac495dSmrg the whole contents. */
5936ac495dSmrg static char *util_firstobj;
6036ac495dSmrg
objc_encoding_init(void)6136ac495dSmrg void objc_encoding_init (void)
6236ac495dSmrg {
6336ac495dSmrg gcc_obstack_init (&util_obstack);
6436ac495dSmrg util_firstobj = (char *) obstack_finish (&util_obstack);
6536ac495dSmrg }
6636ac495dSmrg
6736ac495dSmrg int generating_instance_variables = 0;
6836ac495dSmrg
6936ac495dSmrg static void encode_type_qualifiers (tree);
7036ac495dSmrg static void encode_type (tree, int, int);
7136ac495dSmrg static void encode_field (tree field_decl, int curtype, int format);
7236ac495dSmrg
7336ac495dSmrg static tree
objc_method_parm_type(tree type)7436ac495dSmrg objc_method_parm_type (tree type)
7536ac495dSmrg {
7636ac495dSmrg type = TREE_VALUE (TREE_TYPE (type));
7736ac495dSmrg if (TREE_CODE (type) == TYPE_DECL)
7836ac495dSmrg type = TREE_TYPE (type);
7936ac495dSmrg return type;
8036ac495dSmrg }
8136ac495dSmrg
8236ac495dSmrg static int
objc_encoded_type_size(tree type)8336ac495dSmrg objc_encoded_type_size (tree type)
8436ac495dSmrg {
8536ac495dSmrg int sz = int_size_in_bytes (type);
8636ac495dSmrg
8736ac495dSmrg /* Make all integer and enum types at least as large
8836ac495dSmrg as an int. */
8936ac495dSmrg if (sz > 0 && INTEGRAL_TYPE_P (type))
9036ac495dSmrg sz = MAX (sz, int_size_in_bytes (integer_type_node));
9136ac495dSmrg /* Treat arrays as pointers, since that's how they're
9236ac495dSmrg passed in. */
9336ac495dSmrg else if (TREE_CODE (type) == ARRAY_TYPE)
9436ac495dSmrg sz = int_size_in_bytes (ptr_type_node);
9536ac495dSmrg return sz;
9636ac495dSmrg }
9736ac495dSmrg
9836ac495dSmrg /* Encode a method prototype. */
9936ac495dSmrg tree
encode_method_prototype(tree method_decl)10036ac495dSmrg encode_method_prototype (tree method_decl)
10136ac495dSmrg {
10236ac495dSmrg tree parms;
10336ac495dSmrg int parm_offset, i;
10436ac495dSmrg char buf[40];
10536ac495dSmrg tree result;
10636ac495dSmrg
10736ac495dSmrg /* ONEWAY and BYCOPY, for remote object are the only method qualifiers. */
10836ac495dSmrg encode_type_qualifiers (TREE_PURPOSE (TREE_TYPE (method_decl)));
10936ac495dSmrg
11036ac495dSmrg /* Encode return type. */
11136ac495dSmrg encode_type (objc_method_parm_type (method_decl),
11236ac495dSmrg obstack_object_size (&util_obstack),
11336ac495dSmrg OBJC_ENCODE_INLINE_DEFS);
11436ac495dSmrg
11536ac495dSmrg /* Stack size. */
11636ac495dSmrg /* The first two arguments (self and _cmd) are pointers; account for
11736ac495dSmrg their size. */
11836ac495dSmrg i = int_size_in_bytes (ptr_type_node);
11936ac495dSmrg parm_offset = 2 * i;
12036ac495dSmrg for (parms = METHOD_SEL_ARGS (method_decl); parms;
12136ac495dSmrg parms = DECL_CHAIN (parms))
12236ac495dSmrg {
12336ac495dSmrg tree type = objc_method_parm_type (parms);
12436ac495dSmrg int sz = objc_encoded_type_size (type);
12536ac495dSmrg
12636ac495dSmrg /* If a type size is not known, bail out. */
12736ac495dSmrg if (sz < 0)
12836ac495dSmrg {
12936ac495dSmrg error_at (DECL_SOURCE_LOCATION (method_decl),
13036ac495dSmrg "type %qT does not have a known size",
13136ac495dSmrg type);
13236ac495dSmrg /* Pretend that the encoding succeeded; the compilation will
13336ac495dSmrg fail nevertheless. */
13436ac495dSmrg goto finish_encoding;
13536ac495dSmrg }
13636ac495dSmrg parm_offset += sz;
13736ac495dSmrg }
13836ac495dSmrg
13936ac495dSmrg sprintf (buf, "%d@0:%d", parm_offset, i);
14036ac495dSmrg obstack_grow (&util_obstack, buf, strlen (buf));
14136ac495dSmrg
14236ac495dSmrg /* Argument types. */
14336ac495dSmrg parm_offset = 2 * i;
14436ac495dSmrg for (parms = METHOD_SEL_ARGS (method_decl); parms;
14536ac495dSmrg parms = DECL_CHAIN (parms))
14636ac495dSmrg {
14736ac495dSmrg tree type = objc_method_parm_type (parms);
14836ac495dSmrg
14936ac495dSmrg /* Process argument qualifiers for user supplied arguments. */
15036ac495dSmrg encode_type_qualifiers (TREE_PURPOSE (TREE_TYPE (parms)));
15136ac495dSmrg
15236ac495dSmrg /* Type. */
15336ac495dSmrg encode_type (type, obstack_object_size (&util_obstack),
15436ac495dSmrg OBJC_ENCODE_INLINE_DEFS);
15536ac495dSmrg
15636ac495dSmrg /* Compute offset. */
15736ac495dSmrg sprintf (buf, "%d", parm_offset);
15836ac495dSmrg parm_offset += objc_encoded_type_size (type);
15936ac495dSmrg
16036ac495dSmrg obstack_grow (&util_obstack, buf, strlen (buf));
16136ac495dSmrg }
16236ac495dSmrg
16336ac495dSmrg finish_encoding:
16436ac495dSmrg obstack_1grow (&util_obstack, '\0');
16536ac495dSmrg result = get_identifier (XOBFINISH (&util_obstack, char *));
16636ac495dSmrg obstack_free (&util_obstack, util_firstobj);
16736ac495dSmrg return result;
16836ac495dSmrg }
16936ac495dSmrg
17036ac495dSmrg /* This is used to implement @encode(). */
17136ac495dSmrg tree
objc_build_encode_expr(tree type)17236ac495dSmrg objc_build_encode_expr (tree type)
17336ac495dSmrg {
17436ac495dSmrg tree result;
17536ac495dSmrg const char *string;
17636ac495dSmrg
17736ac495dSmrg encode_type (type, obstack_object_size (&util_obstack),
17836ac495dSmrg OBJC_ENCODE_INLINE_DEFS);
17936ac495dSmrg obstack_1grow (&util_obstack, 0); /* null terminate string */
18036ac495dSmrg string = XOBFINISH (&util_obstack, const char *);
18136ac495dSmrg
18236ac495dSmrg /* Synthesize a string that represents the encoded struct/union. */
18336ac495dSmrg result = my_build_string (strlen (string) + 1, string);
18436ac495dSmrg obstack_free (&util_obstack, util_firstobj);
18536ac495dSmrg return result;
18636ac495dSmrg }
18736ac495dSmrg
18836ac495dSmrg /* "Encode" a data type into a string, which grows in util_obstack.
18936ac495dSmrg
19036ac495dSmrg The format is described in gcc/doc/objc.texi, section 'Type
19136ac495dSmrg encoding'.
19236ac495dSmrg
19336ac495dSmrg Most of the encode_xxx functions have a 'type' argument, which is
19436ac495dSmrg the type to encode, and an integer 'curtype' argument, which is the
19536ac495dSmrg index in the encoding string of the beginning of the encoding of
19636ac495dSmrg the current type, and allows you to find what characters have
19736ac495dSmrg already been written for the current type (they are the ones in the
19836ac495dSmrg current encoding string starting from 'curtype').
19936ac495dSmrg
20036ac495dSmrg For example, if we are encoding a method which returns 'int' and
20136ac495dSmrg takes a 'char **' argument, then when we get to the point of
20236ac495dSmrg encoding the 'char **' argument, the encoded string already
20336ac495dSmrg contains 'i12@0:4' (assuming a pointer size of 4 bytes). So,
20436ac495dSmrg 'curtype' will be set to 7 when starting to encode 'char **'.
20536ac495dSmrg During the whole of the encoding of 'char **', 'curtype' will be
20636ac495dSmrg fixed at 7, so the routine encoding the second pointer can find out
20736ac495dSmrg that it's actually encoding a pointer to a pointer by looking
20836ac495dSmrg backwards at what has already been encoded for the current type,
20936ac495dSmrg and seeing there is a "^" (meaning a pointer) in there. */
21036ac495dSmrg
21136ac495dSmrg
21236ac495dSmrg /* Encode type qualifiers encodes one of the "PQ" Objective-C
21336ac495dSmrg keywords, ie 'in', 'out', 'inout', 'bycopy', 'byref', 'oneway'.
21436ac495dSmrg 'const', instead, is encoded directly as part of the type. */
21536ac495dSmrg static void
encode_type_qualifiers(tree declspecs)21636ac495dSmrg encode_type_qualifiers (tree declspecs)
21736ac495dSmrg {
21836ac495dSmrg tree spec;
21936ac495dSmrg
22036ac495dSmrg for (spec = declspecs; spec; spec = TREE_CHAIN (spec))
22136ac495dSmrg {
22236ac495dSmrg /* FIXME: Shouldn't we use token->keyword here ? */
22336ac495dSmrg if (ridpointers[(int) RID_IN] == TREE_VALUE (spec))
22436ac495dSmrg obstack_1grow (&util_obstack, 'n');
22536ac495dSmrg else if (ridpointers[(int) RID_INOUT] == TREE_VALUE (spec))
22636ac495dSmrg obstack_1grow (&util_obstack, 'N');
22736ac495dSmrg else if (ridpointers[(int) RID_OUT] == TREE_VALUE (spec))
22836ac495dSmrg obstack_1grow (&util_obstack, 'o');
22936ac495dSmrg else if (ridpointers[(int) RID_BYCOPY] == TREE_VALUE (spec))
23036ac495dSmrg obstack_1grow (&util_obstack, 'O');
23136ac495dSmrg else if (ridpointers[(int) RID_BYREF] == TREE_VALUE (spec))
23236ac495dSmrg obstack_1grow (&util_obstack, 'R');
23336ac495dSmrg else if (ridpointers[(int) RID_ONEWAY] == TREE_VALUE (spec))
23436ac495dSmrg obstack_1grow (&util_obstack, 'V');
23536ac495dSmrg else
23636ac495dSmrg gcc_unreachable ();
23736ac495dSmrg }
23836ac495dSmrg }
23936ac495dSmrg
24036ac495dSmrg /* Determine if a pointee is marked read-only. Only used by the NeXT
24136ac495dSmrg runtime to be compatible with gcc-3.3. */
24236ac495dSmrg static bool
pointee_is_readonly(tree pointee)24336ac495dSmrg pointee_is_readonly (tree pointee)
24436ac495dSmrg {
24536ac495dSmrg while (POINTER_TYPE_P (pointee))
24636ac495dSmrg pointee = TREE_TYPE (pointee);
24736ac495dSmrg
24836ac495dSmrg return TYPE_READONLY (pointee);
24936ac495dSmrg }
25036ac495dSmrg
25136ac495dSmrg /* Encode a pointer type. */
25236ac495dSmrg static void
encode_pointer(tree type,int curtype,int format)25336ac495dSmrg encode_pointer (tree type, int curtype, int format)
25436ac495dSmrg {
25536ac495dSmrg tree pointer_to = TREE_TYPE (type);
25636ac495dSmrg
25736ac495dSmrg if (flag_next_runtime)
25836ac495dSmrg {
25936ac495dSmrg /* This code is used to be compatible with gcc-3.3. */
26036ac495dSmrg /* For historical/compatibility reasons, the read-only qualifier
26136ac495dSmrg of the pointee gets emitted _before_ the '^'. The read-only
26236ac495dSmrg qualifier of the pointer itself gets ignored, _unless_ we are
26336ac495dSmrg looking at a typedef! Also, do not emit the 'r' for anything
26436ac495dSmrg but the outermost type! */
26536ac495dSmrg if (!generating_instance_variables
26636ac495dSmrg && (obstack_object_size (&util_obstack) - curtype <= 1)
26736ac495dSmrg && (TYPE_NAME (type) && TREE_CODE (TYPE_NAME (type)) == TYPE_DECL
26836ac495dSmrg ? TYPE_READONLY (type)
26936ac495dSmrg : pointee_is_readonly (pointer_to)))
27036ac495dSmrg obstack_1grow (&util_obstack, 'r');
27136ac495dSmrg }
27236ac495dSmrg
27336ac495dSmrg if (TREE_CODE (pointer_to) == RECORD_TYPE)
27436ac495dSmrg {
27536ac495dSmrg if (OBJC_TYPE_NAME (pointer_to)
27636ac495dSmrg && TREE_CODE (OBJC_TYPE_NAME (pointer_to)) == IDENTIFIER_NODE)
27736ac495dSmrg {
27836ac495dSmrg const char *name = IDENTIFIER_POINTER (OBJC_TYPE_NAME (pointer_to));
27936ac495dSmrg
28036ac495dSmrg if (strcmp (name, TAG_OBJECT) == 0) /* '@' */
28136ac495dSmrg {
28236ac495dSmrg obstack_1grow (&util_obstack, '@');
28336ac495dSmrg return;
28436ac495dSmrg }
28536ac495dSmrg else if (TYPE_HAS_OBJC_INFO (pointer_to)
28636ac495dSmrg && TYPE_OBJC_INTERFACE (pointer_to))
28736ac495dSmrg {
28836ac495dSmrg if (generating_instance_variables)
28936ac495dSmrg {
29036ac495dSmrg obstack_1grow (&util_obstack, '@');
29136ac495dSmrg obstack_1grow (&util_obstack, '"');
29236ac495dSmrg obstack_grow (&util_obstack, name, strlen (name));
29336ac495dSmrg obstack_1grow (&util_obstack, '"');
29436ac495dSmrg return;
29536ac495dSmrg }
29636ac495dSmrg else
29736ac495dSmrg {
29836ac495dSmrg obstack_1grow (&util_obstack, '@');
29936ac495dSmrg return;
30036ac495dSmrg }
30136ac495dSmrg }
30236ac495dSmrg else if (strcmp (name, TAG_CLASS) == 0) /* '#' */
30336ac495dSmrg {
30436ac495dSmrg obstack_1grow (&util_obstack, '#');
30536ac495dSmrg return;
30636ac495dSmrg }
30736ac495dSmrg else if (strcmp (name, TAG_SELECTOR) == 0) /* ':' */
30836ac495dSmrg {
30936ac495dSmrg obstack_1grow (&util_obstack, ':');
31036ac495dSmrg return;
31136ac495dSmrg }
31236ac495dSmrg }
31336ac495dSmrg }
31436ac495dSmrg else if (TREE_CODE (pointer_to) == INTEGER_TYPE
31536ac495dSmrg && TYPE_MODE (pointer_to) == QImode)
31636ac495dSmrg {
31736ac495dSmrg tree pname = TREE_CODE (OBJC_TYPE_NAME (pointer_to)) == IDENTIFIER_NODE
31836ac495dSmrg ? OBJC_TYPE_NAME (pointer_to)
31936ac495dSmrg : DECL_NAME (OBJC_TYPE_NAME (pointer_to));
32036ac495dSmrg
32136ac495dSmrg /* (BOOL *) are an exception and are encoded as ^c, while all
32236ac495dSmrg other pointers to char are encoded as *. */
32336ac495dSmrg if (strcmp (IDENTIFIER_POINTER (pname), "BOOL"))
32436ac495dSmrg {
32536ac495dSmrg if (!flag_next_runtime)
32636ac495dSmrg {
32736ac495dSmrg /* The NeXT runtime adds the 'r' before getting here. */
32836ac495dSmrg
32936ac495dSmrg /* It appears that "r*" means "const char *" rather than
33036ac495dSmrg "char *const". "char *const" is encoded as "*",
33136ac495dSmrg which is identical to "char *", so the "const" is
33236ac495dSmrg unfortunately lost. */
33336ac495dSmrg if (TYPE_READONLY (pointer_to))
33436ac495dSmrg obstack_1grow (&util_obstack, 'r');
33536ac495dSmrg }
33636ac495dSmrg
33736ac495dSmrg obstack_1grow (&util_obstack, '*');
33836ac495dSmrg return;
33936ac495dSmrg }
34036ac495dSmrg }
34136ac495dSmrg
34236ac495dSmrg /* We have a normal pointer type that does not get special treatment. */
34336ac495dSmrg obstack_1grow (&util_obstack, '^');
34436ac495dSmrg encode_type (pointer_to, curtype, format);
34536ac495dSmrg }
34636ac495dSmrg
34736ac495dSmrg static void
encode_array(tree type,int curtype,int format)34836ac495dSmrg encode_array (tree type, int curtype, int format)
34936ac495dSmrg {
35036ac495dSmrg tree an_int_cst = TYPE_SIZE (type);
35136ac495dSmrg tree array_of = TREE_TYPE (type);
35236ac495dSmrg char buffer[40];
35336ac495dSmrg
35436ac495dSmrg if (an_int_cst == NULL)
35536ac495dSmrg {
35636ac495dSmrg /* We are trying to encode an incomplete array. An incomplete
35736ac495dSmrg array is forbidden as part of an instance variable; but it
35836ac495dSmrg may occur if the instance variable is a pointer to such an
35936ac495dSmrg array. */
36036ac495dSmrg
36136ac495dSmrg /* So the only case in which an incomplete array could occur
36236ac495dSmrg (without being pointed to) is if we are encoding the
36336ac495dSmrg arguments or return value of a method. In that case, an
36436ac495dSmrg incomplete array argument or return value (eg,
36536ac495dSmrg -(void)display: (char[])string) is treated like a pointer
36636ac495dSmrg because that is how the compiler does the function call. A
36736ac495dSmrg special, more complicated case, is when the incomplete array
36836ac495dSmrg is the last member of a struct (eg, if we are encoding
36936ac495dSmrg "struct { unsigned long int a;double b[];}"), which is again
37036ac495dSmrg part of a method argument/return value. In that case, we
37136ac495dSmrg really need to communicate to the runtime that there is an
37236ac495dSmrg incomplete array (not a pointer!) there. So, we detect that
37336ac495dSmrg special case and encode it as a zero-length array.
37436ac495dSmrg
37536ac495dSmrg Try to detect that we are part of a struct. We do this by
37636ac495dSmrg searching for '=' in the type encoding for the current type.
37736ac495dSmrg NB: This hack assumes that you can't use '=' as part of a C
37836ac495dSmrg identifier.
37936ac495dSmrg */
38036ac495dSmrg {
38136ac495dSmrg char *enc = (char *) obstack_base (&util_obstack) + curtype;
38236ac495dSmrg if (memchr (enc, '=',
38336ac495dSmrg obstack_object_size (&util_obstack) - curtype) == NULL)
38436ac495dSmrg {
38536ac495dSmrg /* We are not inside a struct. Encode the array as a
38636ac495dSmrg pointer. */
38736ac495dSmrg encode_pointer (type, curtype, format);
38836ac495dSmrg return;
38936ac495dSmrg }
39036ac495dSmrg }
39136ac495dSmrg
39236ac495dSmrg /* Else, we are in a struct, and we encode it as a zero-length
39336ac495dSmrg array. */
39436ac495dSmrg sprintf (buffer, "[" HOST_WIDE_INT_PRINT_DEC, (HOST_WIDE_INT)0);
39536ac495dSmrg }
39636ac495dSmrg else if (TREE_INT_CST_LOW (TYPE_SIZE (array_of)) == 0)
39736ac495dSmrg sprintf (buffer, "[" HOST_WIDE_INT_PRINT_DEC, (HOST_WIDE_INT)0);
39836ac495dSmrg else
39936ac495dSmrg sprintf (buffer, "[" HOST_WIDE_INT_PRINT_DEC,
40036ac495dSmrg TREE_INT_CST_LOW (an_int_cst)
40136ac495dSmrg / TREE_INT_CST_LOW (TYPE_SIZE (array_of)));
40236ac495dSmrg
40336ac495dSmrg obstack_grow (&util_obstack, buffer, strlen (buffer));
40436ac495dSmrg encode_type (array_of, curtype, format);
40536ac495dSmrg obstack_1grow (&util_obstack, ']');
40636ac495dSmrg return;
40736ac495dSmrg }
40836ac495dSmrg
40936ac495dSmrg /* Encode a vector. The vector type is a GCC extension to C. */
41036ac495dSmrg static void
encode_vector(tree type,int curtype,int format)41136ac495dSmrg encode_vector (tree type, int curtype, int format)
41236ac495dSmrg {
41336ac495dSmrg tree vector_of = TREE_TYPE (type);
41436ac495dSmrg char buffer[40];
41536ac495dSmrg
41636ac495dSmrg /* Vectors are like simple fixed-size arrays. */
41736ac495dSmrg
41836ac495dSmrg /* Output ![xx,yy,<code>] where xx is the vector_size, yy is the
41936ac495dSmrg alignment of the vector, and <code> is the base type. Eg, int
42036ac495dSmrg __attribute__ ((vector_size (16))) gets encoded as ![16,32,i]
42136ac495dSmrg assuming that the alignment is 32 bytes. We include size and
42236ac495dSmrg alignment in bytes so that the runtime does not have to have any
42336ac495dSmrg knowledge of the actual types.
42436ac495dSmrg */
42536ac495dSmrg sprintf (buffer, "![" HOST_WIDE_INT_PRINT_DEC ",%d",
42636ac495dSmrg /* We want to compute the equivalent of sizeof (<vector>).
42736ac495dSmrg Code inspired by c_sizeof_or_alignof_type. */
42836ac495dSmrg ((TREE_INT_CST_LOW (TYPE_SIZE_UNIT (type))
42936ac495dSmrg / (TYPE_PRECISION (char_type_node) / BITS_PER_UNIT))),
43036ac495dSmrg /* We want to compute the equivalent of __alignof__
43136ac495dSmrg (<vector>). Code inspired by
43236ac495dSmrg c_sizeof_or_alignof_type. */
43336ac495dSmrg TYPE_ALIGN_UNIT (type));
43436ac495dSmrg obstack_grow (&util_obstack, buffer, strlen (buffer));
43536ac495dSmrg encode_type (vector_of, curtype, format);
43636ac495dSmrg obstack_1grow (&util_obstack, ']');
43736ac495dSmrg return;
43836ac495dSmrg }
43936ac495dSmrg
44036ac495dSmrg static void
encode_aggregate_fields(tree type,bool pointed_to,int curtype,int format)44136ac495dSmrg encode_aggregate_fields (tree type, bool pointed_to, int curtype, int format)
44236ac495dSmrg {
44336ac495dSmrg tree field = TYPE_FIELDS (type);
44436ac495dSmrg
44536ac495dSmrg for (; field; field = DECL_CHAIN (field))
44636ac495dSmrg {
44736ac495dSmrg #ifdef OBJCPLUS
44836ac495dSmrg /* C++ static members, and things that are not field at all,
44936ac495dSmrg should not appear in the encoding. */
45036ac495dSmrg if (TREE_CODE (field) != FIELD_DECL || TREE_STATIC (field))
45136ac495dSmrg continue;
45236ac495dSmrg #endif
45336ac495dSmrg
45436ac495dSmrg /* Recursively encode fields of embedded base classes. */
45536ac495dSmrg if (DECL_ARTIFICIAL (field) && !DECL_NAME (field)
45636ac495dSmrg && TREE_CODE (TREE_TYPE (field)) == RECORD_TYPE)
45736ac495dSmrg {
45836ac495dSmrg encode_aggregate_fields (TREE_TYPE (field),
45936ac495dSmrg pointed_to, curtype, format);
46036ac495dSmrg continue;
46136ac495dSmrg }
46236ac495dSmrg
46336ac495dSmrg if (generating_instance_variables && !pointed_to)
46436ac495dSmrg {
46536ac495dSmrg tree fname = DECL_NAME (field);
46636ac495dSmrg
46736ac495dSmrg obstack_1grow (&util_obstack, '"');
46836ac495dSmrg
46936ac495dSmrg if (fname && TREE_CODE (fname) == IDENTIFIER_NODE)
47036ac495dSmrg obstack_grow (&util_obstack,
47136ac495dSmrg IDENTIFIER_POINTER (fname),
47236ac495dSmrg strlen (IDENTIFIER_POINTER (fname)));
47336ac495dSmrg
47436ac495dSmrg obstack_1grow (&util_obstack, '"');
47536ac495dSmrg }
47636ac495dSmrg
47736ac495dSmrg encode_field (field, curtype, format);
47836ac495dSmrg }
47936ac495dSmrg }
48036ac495dSmrg
48136ac495dSmrg static void
encode_aggregate_within(tree type,int curtype,int format,int left,int right)48236ac495dSmrg encode_aggregate_within (tree type, int curtype, int format, int left,
48336ac495dSmrg int right)
48436ac495dSmrg {
48536ac495dSmrg tree name;
48636ac495dSmrg /* NB: aggregates that are pointed to have slightly different encoding
48736ac495dSmrg rules in that you never encode the names of instance variables. */
48836ac495dSmrg int ob_size = obstack_object_size (&util_obstack);
48936ac495dSmrg bool inline_contents = false;
49036ac495dSmrg bool pointed_to = false;
49136ac495dSmrg
49236ac495dSmrg if (flag_next_runtime)
49336ac495dSmrg {
49436ac495dSmrg if (ob_size > 0
49536ac495dSmrg && *((char *) obstack_next_free (&util_obstack) - 1) == '^')
49636ac495dSmrg pointed_to = true;
49736ac495dSmrg
49836ac495dSmrg if ((format == OBJC_ENCODE_INLINE_DEFS || generating_instance_variables)
49936ac495dSmrg && (!pointed_to || ob_size - curtype == 1
50036ac495dSmrg || (ob_size - curtype == 2
50136ac495dSmrg && *((char *) obstack_next_free (&util_obstack) - 2) == 'r')))
50236ac495dSmrg inline_contents = true;
50336ac495dSmrg }
50436ac495dSmrg else
50536ac495dSmrg {
50636ac495dSmrg /* c0 and c1 are the last two characters in the encoding of the
50736ac495dSmrg current type; if the last two characters were '^' or '^r',
50836ac495dSmrg then we are encoding an aggregate that is "pointed to". The
50936ac495dSmrg comment above applies: in that case we should avoid encoding
51036ac495dSmrg the names of instance variables.
51136ac495dSmrg */
51236ac495dSmrg char c0, c1;
51336ac495dSmrg
51436ac495dSmrg c1 = ob_size > 1 ? *((char *) obstack_next_free (&util_obstack) - 2) : 0;
51536ac495dSmrg c0 = ob_size > 0 ? *((char *) obstack_next_free (&util_obstack) - 1) : 0;
51636ac495dSmrg if (c0 == '^' || (c1 == '^' && c0 == 'r'))
51736ac495dSmrg pointed_to = true;
51836ac495dSmrg
51936ac495dSmrg if (format == OBJC_ENCODE_INLINE_DEFS || generating_instance_variables)
52036ac495dSmrg {
52136ac495dSmrg if (!pointed_to)
52236ac495dSmrg inline_contents = true;
52336ac495dSmrg else
52436ac495dSmrg {
52536ac495dSmrg /* Note that the check (ob_size - curtype < 2) prevents
52636ac495dSmrg infinite recursion when encoding a structure which is
52736ac495dSmrg a linked list (eg, struct node { struct node *next;
52836ac495dSmrg }). Each time we follow a pointer, we add one
52936ac495dSmrg character to ob_size, and curtype is fixed, so after
53036ac495dSmrg at most two pointers we stop inlining contents and
53136ac495dSmrg break the loop.
53236ac495dSmrg
53336ac495dSmrg The other case where we don't inline is "^r", which
53436ac495dSmrg is a pointer to a constant struct.
53536ac495dSmrg */
53636ac495dSmrg if ((ob_size - curtype <= 2) && !(c0 == 'r'))
53736ac495dSmrg inline_contents = true;
53836ac495dSmrg }
53936ac495dSmrg }
54036ac495dSmrg }
54136ac495dSmrg
54236ac495dSmrg /* Traverse struct aliases; it is important to get the
54336ac495dSmrg original struct and its tag name (if any). */
54436ac495dSmrg type = TYPE_MAIN_VARIANT (type);
54536ac495dSmrg name = OBJC_TYPE_NAME (type);
54636ac495dSmrg /* Open parenth/bracket. */
54736ac495dSmrg obstack_1grow (&util_obstack, left);
54836ac495dSmrg
54936ac495dSmrg /* Encode the struct/union tag name, or '?' if a tag was
55036ac495dSmrg not provided. Typedef aliases do not qualify. */
55136ac495dSmrg #ifdef OBJCPLUS
55236ac495dSmrg /* For compatibility with the NeXT runtime, ObjC++ encodes template
55336ac495dSmrg args as a composite struct tag name. */
55436ac495dSmrg if (name && TREE_CODE (name) == IDENTIFIER_NODE
55536ac495dSmrg /* Did this struct have a tag? */
55636ac495dSmrg && !TYPE_WAS_UNNAMED (type))
55736ac495dSmrg obstack_grow (&util_obstack,
55836ac495dSmrg decl_as_string (type, TFF_DECL_SPECIFIERS | TFF_UNQUALIFIED_NAME),
55936ac495dSmrg strlen (decl_as_string (type, TFF_DECL_SPECIFIERS | TFF_UNQUALIFIED_NAME)));
56036ac495dSmrg #else
56136ac495dSmrg if (name && TREE_CODE (name) == IDENTIFIER_NODE)
56236ac495dSmrg obstack_grow (&util_obstack,
56336ac495dSmrg IDENTIFIER_POINTER (name),
56436ac495dSmrg strlen (IDENTIFIER_POINTER (name)));
56536ac495dSmrg #endif
56636ac495dSmrg else
56736ac495dSmrg obstack_1grow (&util_obstack, '?');
56836ac495dSmrg
56936ac495dSmrg /* Encode the types (and possibly names) of the inner fields,
57036ac495dSmrg if required. */
57136ac495dSmrg if (inline_contents)
57236ac495dSmrg {
57336ac495dSmrg obstack_1grow (&util_obstack, '=');
57436ac495dSmrg encode_aggregate_fields (type, pointed_to, curtype, format);
57536ac495dSmrg }
57636ac495dSmrg /* Close parenth/bracket. */
57736ac495dSmrg obstack_1grow (&util_obstack, right);
57836ac495dSmrg }
57936ac495dSmrg
58036ac495dSmrg /* Encode a bitfield NeXT-style (i.e., without a bit offset or the underlying
58136ac495dSmrg field type. */
58236ac495dSmrg static void
encode_next_bitfield(int width)58336ac495dSmrg encode_next_bitfield (int width)
58436ac495dSmrg {
58536ac495dSmrg char buffer[40];
58636ac495dSmrg sprintf (buffer, "b%d", width);
58736ac495dSmrg obstack_grow (&util_obstack, buffer, strlen (buffer));
58836ac495dSmrg }
58936ac495dSmrg
59036ac495dSmrg /* Encodes 'type', ignoring type qualifiers (which you should encode
59136ac495dSmrg beforehand if needed) with the exception of 'const', which is
59236ac495dSmrg encoded by encode_type. See above for the explanation of
59336ac495dSmrg 'curtype'. 'format' can be OBJC_ENCODE_INLINE_DEFS or
59436ac495dSmrg OBJC_ENCODE_DONT_INLINE_DEFS. */
59536ac495dSmrg static void
encode_type(tree type,int curtype,int format)59636ac495dSmrg encode_type (tree type, int curtype, int format)
59736ac495dSmrg {
59836ac495dSmrg enum tree_code code = TREE_CODE (type);
59936ac495dSmrg
60036ac495dSmrg /* Ignore type qualifiers other than 'const' when encoding a
60136ac495dSmrg type. */
60236ac495dSmrg
60336ac495dSmrg if (type == error_mark_node)
60436ac495dSmrg return;
60536ac495dSmrg
60636ac495dSmrg if (!flag_next_runtime)
60736ac495dSmrg {
60836ac495dSmrg if (TYPE_READONLY (type))
60936ac495dSmrg obstack_1grow (&util_obstack, 'r');
61036ac495dSmrg }
61136ac495dSmrg
61236ac495dSmrg switch (code)
61336ac495dSmrg {
61436ac495dSmrg case ENUMERAL_TYPE:
61536ac495dSmrg if (flag_next_runtime)
61636ac495dSmrg {
61736ac495dSmrg /* Kludge for backwards-compatibility with gcc-3.3: enums
61836ac495dSmrg are always encoded as 'i' no matter what type they
61936ac495dSmrg actually are (!). */
62036ac495dSmrg obstack_1grow (&util_obstack, 'i');
62136ac495dSmrg break;
62236ac495dSmrg }
62336ac495dSmrg /* Else, they are encoded exactly like the integer type that is
62436ac495dSmrg used by the compiler to store them. */
62536ac495dSmrg /* FALLTHRU */
62636ac495dSmrg case INTEGER_TYPE:
62736ac495dSmrg {
62836ac495dSmrg char c;
629a2dc1f3fSmrg switch (GET_MODE_BITSIZE (SCALAR_INT_TYPE_MODE (type)))
63036ac495dSmrg {
63136ac495dSmrg case 8: c = TYPE_UNSIGNED (type) ? 'C' : 'c'; break;
63236ac495dSmrg case 16: c = TYPE_UNSIGNED (type) ? 'S' : 's'; break;
63336ac495dSmrg case 32:
63436ac495dSmrg {
63536ac495dSmrg tree int_type = type;
63636ac495dSmrg if (flag_next_runtime)
63736ac495dSmrg {
63836ac495dSmrg /* Another legacy kludge for compatibility with
63936ac495dSmrg gcc-3.3: 32-bit longs are encoded as 'l' or 'L',
64036ac495dSmrg but not always. For typedefs, we need to use 'i'
64136ac495dSmrg or 'I' instead if encoding a struct field, or a
64236ac495dSmrg pointer! */
64336ac495dSmrg int_type = ((!generating_instance_variables
64436ac495dSmrg && (obstack_object_size (&util_obstack)
64536ac495dSmrg == (unsigned) curtype))
64636ac495dSmrg ? TYPE_MAIN_VARIANT (type)
64736ac495dSmrg : type);
64836ac495dSmrg }
64936ac495dSmrg if (int_type == long_unsigned_type_node
65036ac495dSmrg || int_type == long_integer_type_node)
65136ac495dSmrg c = TYPE_UNSIGNED (type) ? 'L' : 'l';
65236ac495dSmrg else
65336ac495dSmrg c = TYPE_UNSIGNED (type) ? 'I' : 'i';
65436ac495dSmrg }
65536ac495dSmrg break;
65636ac495dSmrg case 64: c = TYPE_UNSIGNED (type) ? 'Q' : 'q'; break;
65736ac495dSmrg case 128: c = TYPE_UNSIGNED (type) ? 'T' : 't'; break;
65836ac495dSmrg default: gcc_unreachable ();
65936ac495dSmrg }
66036ac495dSmrg obstack_1grow (&util_obstack, c);
66136ac495dSmrg break;
66236ac495dSmrg }
66336ac495dSmrg case REAL_TYPE:
66436ac495dSmrg {
66536ac495dSmrg char c;
66636ac495dSmrg /* Floating point types. */
667a2dc1f3fSmrg switch (GET_MODE_BITSIZE (SCALAR_FLOAT_TYPE_MODE (type)))
66836ac495dSmrg {
66936ac495dSmrg case 32: c = 'f'; break;
67036ac495dSmrg case 64: c = 'd'; break;
67136ac495dSmrg case 96:
67236ac495dSmrg case 128: c = 'D'; break;
67336ac495dSmrg default: gcc_unreachable ();
67436ac495dSmrg }
67536ac495dSmrg obstack_1grow (&util_obstack, c);
67636ac495dSmrg break;
67736ac495dSmrg }
67836ac495dSmrg case VOID_TYPE:
67936ac495dSmrg obstack_1grow (&util_obstack, 'v');
68036ac495dSmrg break;
68136ac495dSmrg
68236ac495dSmrg case BOOLEAN_TYPE:
68336ac495dSmrg obstack_1grow (&util_obstack, 'B');
68436ac495dSmrg break;
68536ac495dSmrg
68636ac495dSmrg case ARRAY_TYPE:
68736ac495dSmrg encode_array (type, curtype, format);
68836ac495dSmrg break;
68936ac495dSmrg
69036ac495dSmrg case POINTER_TYPE:
69136ac495dSmrg #ifdef OBJCPLUS
69236ac495dSmrg case REFERENCE_TYPE:
69336ac495dSmrg #endif
69436ac495dSmrg encode_pointer (type, curtype, format);
69536ac495dSmrg break;
69636ac495dSmrg
69736ac495dSmrg case RECORD_TYPE:
69836ac495dSmrg encode_aggregate_within (type, curtype, format, '{', '}');
69936ac495dSmrg break;
70036ac495dSmrg
70136ac495dSmrg case UNION_TYPE:
70236ac495dSmrg encode_aggregate_within (type, curtype, format, '(', ')');
70336ac495dSmrg break;
70436ac495dSmrg
70536ac495dSmrg case FUNCTION_TYPE: /* '?' means an unknown type. */
70636ac495dSmrg obstack_1grow (&util_obstack, '?');
70736ac495dSmrg break;
70836ac495dSmrg
70936ac495dSmrg case COMPLEX_TYPE:
71036ac495dSmrg /* A complex is encoded as 'j' followed by the inner type (eg,
71136ac495dSmrg "_Complex int" is encoded as 'ji'). */
71236ac495dSmrg obstack_1grow (&util_obstack, 'j');
71336ac495dSmrg encode_type (TREE_TYPE (type), curtype, format);
71436ac495dSmrg break;
71536ac495dSmrg
71636ac495dSmrg case VECTOR_TYPE:
71736ac495dSmrg encode_vector (type, curtype, format);
71836ac495dSmrg break;
71936ac495dSmrg
72036ac495dSmrg default:
72136ac495dSmrg warning (0, "unknown type %<%T%> found during Objective-C encoding",
72236ac495dSmrg TREE_TYPE (type));
72336ac495dSmrg obstack_1grow (&util_obstack, '?');
72436ac495dSmrg break;
72536ac495dSmrg }
72636ac495dSmrg
72736ac495dSmrg if (flag_next_runtime)
72836ac495dSmrg {
72936ac495dSmrg /* Super-kludge. Some ObjC qualifier and type combinations need
73036ac495dSmrg to be rearranged for compatibility with gcc-3.3. */
73136ac495dSmrg if (code == POINTER_TYPE && obstack_object_size (&util_obstack) >= 3)
73236ac495dSmrg {
73336ac495dSmrg char *enc = (char *) obstack_base (&util_obstack) + curtype;
73436ac495dSmrg
73536ac495dSmrg /* Rewrite "in const" from "nr" to "rn". */
73636ac495dSmrg if (curtype >= 1 && !strncmp (enc - 1, "nr", 2))
737a2dc1f3fSmrg memcpy (enc - 1, "rn", 2);
73836ac495dSmrg }
73936ac495dSmrg }
74036ac495dSmrg }
74136ac495dSmrg
74236ac495dSmrg static void
encode_gnu_bitfield(int position,tree type,int size)74336ac495dSmrg encode_gnu_bitfield (int position, tree type, int size)
74436ac495dSmrg {
74536ac495dSmrg enum tree_code code = TREE_CODE (type);
74636ac495dSmrg char buffer[40];
74736ac495dSmrg char charType = '?';
74836ac495dSmrg
74936ac495dSmrg /* This code is only executed for the GNU runtime, so we can ignore
75036ac495dSmrg the NeXT runtime kludge of always encoding enums as 'i' no matter
75136ac495dSmrg what integers they actually are. */
75236ac495dSmrg if (code == INTEGER_TYPE || code == ENUMERAL_TYPE)
75336ac495dSmrg {
75436ac495dSmrg if (integer_zerop (TYPE_MIN_VALUE (type)))
75536ac495dSmrg /* Unsigned integer types. */
75636ac495dSmrg {
75736ac495dSmrg switch (TYPE_MODE (type))
75836ac495dSmrg {
759a2dc1f3fSmrg case E_QImode:
76036ac495dSmrg charType = 'C'; break;
761a2dc1f3fSmrg case E_HImode:
76236ac495dSmrg charType = 'S'; break;
763a2dc1f3fSmrg case E_SImode:
76436ac495dSmrg {
76536ac495dSmrg if (type == long_unsigned_type_node)
76636ac495dSmrg charType = 'L';
76736ac495dSmrg else
76836ac495dSmrg charType = 'I';
76936ac495dSmrg break;
77036ac495dSmrg }
771a2dc1f3fSmrg case E_DImode:
77236ac495dSmrg charType = 'Q'; break;
77336ac495dSmrg default:
77436ac495dSmrg gcc_unreachable ();
77536ac495dSmrg }
77636ac495dSmrg }
77736ac495dSmrg else
77836ac495dSmrg /* Signed integer types. */
77936ac495dSmrg {
78036ac495dSmrg switch (TYPE_MODE (type))
78136ac495dSmrg {
782a2dc1f3fSmrg case E_QImode:
78336ac495dSmrg charType = 'c'; break;
784a2dc1f3fSmrg case E_HImode:
78536ac495dSmrg charType = 's'; break;
786a2dc1f3fSmrg case E_SImode:
78736ac495dSmrg {
78836ac495dSmrg if (type == long_integer_type_node)
78936ac495dSmrg charType = 'l';
79036ac495dSmrg else
79136ac495dSmrg charType = 'i';
79236ac495dSmrg break;
79336ac495dSmrg }
794a2dc1f3fSmrg case E_DImode:
79536ac495dSmrg charType = 'q'; break;
79636ac495dSmrg default:
79736ac495dSmrg gcc_unreachable ();
79836ac495dSmrg }
79936ac495dSmrg }
80036ac495dSmrg }
80136ac495dSmrg else
80236ac495dSmrg {
80336ac495dSmrg /* Do not do any encoding, produce an error and keep going. */
804*8feb0f0bSmrg error ("trying to encode non-integer type as a bit-field");
80536ac495dSmrg return;
80636ac495dSmrg }
80736ac495dSmrg
80836ac495dSmrg sprintf (buffer, "b%d%c%d", position, charType, size);
80936ac495dSmrg obstack_grow (&util_obstack, buffer, strlen (buffer));
81036ac495dSmrg }
81136ac495dSmrg
81236ac495dSmrg static void
encode_field(tree field_decl,int curtype,int format)81336ac495dSmrg encode_field (tree field_decl, int curtype, int format)
81436ac495dSmrg {
81536ac495dSmrg #ifdef OBJCPLUS
81636ac495dSmrg /* C++ static members, and things that are not fields at all,
81736ac495dSmrg should not appear in the encoding. */
81836ac495dSmrg if (TREE_CODE (field_decl) != FIELD_DECL || TREE_STATIC (field_decl))
81936ac495dSmrg return;
82036ac495dSmrg #endif
82136ac495dSmrg
82236ac495dSmrg /* Generate the bitfield typing information, if needed. Note the difference
82336ac495dSmrg between GNU and NeXT runtimes. */
82436ac495dSmrg if (DECL_BIT_FIELD_TYPE (field_decl))
82536ac495dSmrg {
82636ac495dSmrg int size = tree_to_uhwi (DECL_SIZE (field_decl));
82736ac495dSmrg
82836ac495dSmrg if (flag_next_runtime)
82936ac495dSmrg encode_next_bitfield (size);
83036ac495dSmrg else
83136ac495dSmrg encode_gnu_bitfield (int_bit_position (field_decl),
83236ac495dSmrg DECL_BIT_FIELD_TYPE (field_decl), size);
83336ac495dSmrg }
83436ac495dSmrg else
83536ac495dSmrg encode_type (TREE_TYPE (field_decl), curtype, format);
83636ac495dSmrg }
83736ac495dSmrg
83836ac495dSmrg tree
encode_field_decl(tree field_decl)83936ac495dSmrg encode_field_decl (tree field_decl)
84036ac495dSmrg {
84136ac495dSmrg tree result;
84236ac495dSmrg
84336ac495dSmrg encode_field (field_decl,
84436ac495dSmrg obstack_object_size (&util_obstack),
84536ac495dSmrg OBJC_ENCODE_DONT_INLINE_DEFS);
84636ac495dSmrg
84736ac495dSmrg /* Null terminate string. */
84836ac495dSmrg obstack_1grow (&util_obstack, 0);
84936ac495dSmrg
85036ac495dSmrg /* Get identifier for the string. */
85136ac495dSmrg result = get_identifier (XOBFINISH (&util_obstack, char *));
85236ac495dSmrg obstack_free (&util_obstack, util_firstobj);
85336ac495dSmrg
85436ac495dSmrg return result;
85536ac495dSmrg }
85636ac495dSmrg
85736ac495dSmrg /* This routine encodes the attribute of the input PROPERTY according
85836ac495dSmrg to following formula:
85936ac495dSmrg
86036ac495dSmrg Property attributes are stored as a comma-delimited C string.
86136ac495dSmrg Simple attributes such as readonly are encoded as single
86236ac495dSmrg character. The parametrized attributes, getter=name and
86336ac495dSmrg setter=name, are encoded as a single character followed by an
86436ac495dSmrg identifier. Property types are also encoded as a parametrized
86536ac495dSmrg attribute. The characters used to encode these attributes are
86636ac495dSmrg defined by the following enumeration:
86736ac495dSmrg
86836ac495dSmrg enum PropertyAttributes {
86936ac495dSmrg kPropertyReadOnly = 'R',
87036ac495dSmrg kPropertyBycopy = 'C',
87136ac495dSmrg kPropertyByref = '&',
87236ac495dSmrg kPropertyDynamic = 'D',
87336ac495dSmrg kPropertyGetter = 'G',
87436ac495dSmrg kPropertySetter = 'S',
87536ac495dSmrg kPropertyInstanceVariable = 'V',
87636ac495dSmrg kPropertyType = 'T',
87736ac495dSmrg kPropertyWeak = 'W',
87836ac495dSmrg kPropertyStrong = 'P',
87936ac495dSmrg kPropertyNonAtomic = 'N'
88036ac495dSmrg }; */
88136ac495dSmrg tree
objc_v2_encode_prop_attr(tree property)88236ac495dSmrg objc_v2_encode_prop_attr (tree property)
88336ac495dSmrg {
88436ac495dSmrg const char *string;
88536ac495dSmrg tree type = TREE_TYPE (property);
88636ac495dSmrg
88736ac495dSmrg obstack_1grow (&util_obstack, 'T');
88836ac495dSmrg encode_type (type, obstack_object_size (&util_obstack),
88936ac495dSmrg OBJC_ENCODE_INLINE_DEFS);
89036ac495dSmrg
89136ac495dSmrg if (PROPERTY_READONLY (property))
89236ac495dSmrg obstack_grow (&util_obstack, ",R", 2);
89336ac495dSmrg
89436ac495dSmrg switch (PROPERTY_ASSIGN_SEMANTICS (property))
89536ac495dSmrg {
89636ac495dSmrg case OBJC_PROPERTY_COPY:
89736ac495dSmrg obstack_grow (&util_obstack, ",C", 2);
89836ac495dSmrg break;
89936ac495dSmrg case OBJC_PROPERTY_RETAIN:
90036ac495dSmrg obstack_grow (&util_obstack, ",&", 2);
90136ac495dSmrg break;
90236ac495dSmrg case OBJC_PROPERTY_ASSIGN:
90336ac495dSmrg default:
90436ac495dSmrg break;
90536ac495dSmrg }
90636ac495dSmrg
90736ac495dSmrg if (PROPERTY_DYNAMIC (property))
90836ac495dSmrg obstack_grow (&util_obstack, ",D", 2);
90936ac495dSmrg
91036ac495dSmrg if (PROPERTY_NONATOMIC (property))
91136ac495dSmrg obstack_grow (&util_obstack, ",N", 2);
91236ac495dSmrg
91336ac495dSmrg /* Here we want to encode the getter name, but only if it's not the
91436ac495dSmrg standard one. */
91536ac495dSmrg if (PROPERTY_GETTER_NAME (property) != PROPERTY_NAME (property))
91636ac495dSmrg {
91736ac495dSmrg obstack_grow (&util_obstack, ",G", 2);
91836ac495dSmrg string = IDENTIFIER_POINTER (PROPERTY_GETTER_NAME (property));
91936ac495dSmrg obstack_grow (&util_obstack, string, strlen (string));
92036ac495dSmrg }
92136ac495dSmrg
92236ac495dSmrg if (!PROPERTY_READONLY (property))
92336ac495dSmrg {
92436ac495dSmrg /* Here we want to encode the setter name, but only if it's not
92536ac495dSmrg the standard one. */
92636ac495dSmrg tree standard_setter = get_identifier (objc_build_property_setter_name (PROPERTY_NAME (property)));
92736ac495dSmrg if (PROPERTY_SETTER_NAME (property) != standard_setter)
92836ac495dSmrg {
92936ac495dSmrg obstack_grow (&util_obstack, ",S", 2);
93036ac495dSmrg string = IDENTIFIER_POINTER (PROPERTY_SETTER_NAME (property));
93136ac495dSmrg obstack_grow (&util_obstack, string, strlen (string));
93236ac495dSmrg }
93336ac495dSmrg }
93436ac495dSmrg
93536ac495dSmrg /* TODO: Encode strong ('P'), weak ('W') for garbage collection. */
93636ac495dSmrg
93736ac495dSmrg if (!PROPERTY_DYNAMIC (property))
93836ac495dSmrg {
93936ac495dSmrg obstack_grow (&util_obstack, ",V", 2);
94036ac495dSmrg if (PROPERTY_IVAR_NAME (property))
94136ac495dSmrg string = IDENTIFIER_POINTER (PROPERTY_IVAR_NAME (property));
94236ac495dSmrg else
94336ac495dSmrg string = IDENTIFIER_POINTER (PROPERTY_NAME (property));
94436ac495dSmrg obstack_grow (&util_obstack, string, strlen (string));
94536ac495dSmrg }
94636ac495dSmrg
94736ac495dSmrg /* NULL-terminate string. */
94836ac495dSmrg obstack_1grow (&util_obstack, 0);
94936ac495dSmrg string = XOBFINISH (&util_obstack, char *);
95036ac495dSmrg obstack_free (&util_obstack, util_firstobj);
95136ac495dSmrg return get_identifier (string);
95236ac495dSmrg }
953