summaryrefslogtreecommitdiff
path: root/gcc/objc
diff options
context:
space:
mode:
authornicola <nicola@138bc75d-0d04-0410-961f-82ee72b054a4>2011-07-04 08:02:50 +0000
committernicola <nicola@138bc75d-0d04-0410-961f-82ee72b054a4>2011-07-04 08:02:50 +0000
commitf572c7ba80bd1cea27695565542722e63dcdfc9e (patch)
treecb74883a8d479cb7d23bc099e02c2f37121c8ed6 /gcc/objc
parented496df154a041533fbc99b048b2354988a07aae (diff)
downloadgcc-f572c7ba80bd1cea27695565542722e63dcdfc9e.tar.gz
In gcc/objc/:
2011-07-04 Nicola Pero <nicola.pero@meta-innovation.com> Refactored encoding code into objc-encoding.h and objc-encoding.c. * objc-act.c (util_obstack, util_firstobj, encode_type_qualifiers, encode_type, generating_instance_variables, objc_method_parm_type, objc_encoded_type_size, encode_method_prototype, objc_build_encode_expr, pointee_is_readonly, encode_pointer, encode_array, encode_vector, encode_aggregate_fields, encode_aggregate_within, encode_next_bitfield, encode_gnu_bitfield, encode_field_decl, objc_v2_encode_property_attr): Moved to objc-encoding.h and objc-encoding.c. No change in the actual code. Include objc-encoding.h. (objc_init): Added TODO. (objc_build_property_setter_name): Made non-static so it can be called from objc-encoding.c. * objc-act.h (OBJC_ENCODE_INLINE_DEFS, OBJC_ENCODE_DONT_INLINE_DEFS): Moved to objc-encoding.h. * objc-runtime-shared-support.h (objc_v2_encode_property_attr, encode_method_prototype, encode_field_decl, generating_instance_variables): Moved to objc-encoding.h. (objc_build_property_setter_name): Declare. * objc-encoding.c: New. * objc-encoding.h: New. * objc-gnu-runtime-abi-01.c: Include objc-encoding.h. * objc-next-runtime-abi-01.c: Likewise. * objc-next-runtime-abi-02.c: Likewise. * objc-runtime-shared-support.c: Likewise. * Make-lang.in (OBJC_OBJS): Added objc-encoding.o. (objc/objc-lang.o): Reordered dependencies. (objc/objc-runtime-shared-support.o): Reordered dependencies. Added dependencies on objc-encoding.h and on $(GGC_H), $(DIAGNOSTIC_CORE_H), $(FLAGS_H) and input.h. (objc/objc-gnu-runtime-abi-01.o): Likewise. (objc/objc-next-runtime-abi-01.o): Likewise. (objc/objc-next-runtime-abi-02.o): Likewise. (objc/objc-act.o): Reordered dependencies. Added dependency on objc-encoding.h. (objc/objc-encoding.o): New rule. * objc-encoding.c (encode_type): Use "%<%T%>" format when printing warning "unknown type %<%T%> found during Objective-C encoding" instead of using gen_type_name. In gcc/objcp/: 2011-07-04 Nicola Pero <nicola.pero@meta-innovation.com> * Make-lang.in (OBJCXX_OBJS): Added objc-encoding.o. (objcp/objcp-lang.o): Reordered dependencies. Depend on GGC_H. (objcp/objcp-decl.o): Reordered dependencies. (objcp/objc-runtime-shared-support.o): Reordered dependencies. Updated them to be identical to the corresponding new objc/ ones, with the addition of objcp-decl.h. (objcp/objc-runtime-shared-support.o): Likewise. (objcp/objc-gnu-runtime-abi-01.o): Likewise. (objcp/objc-next-runtime-abi-01.o): Likewise. (objcp/objc-next-runtime-abi-02.o): Likewise. (objcp/objcp-act.o): Reordered dependencies. Added dependency on objc-encoding.h. (objcp/objc-encoding.o): New rule. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@175797 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/objc')
-rw-r--r--gcc/objc/ChangeLog44
-rw-r--r--gcc/objc/Make-lang.in91
-rw-r--r--gcc/objc/objc-act.c906
-rw-r--r--gcc/objc/objc-act.h4
-rw-r--r--gcc/objc/objc-encoding.c926
-rw-r--r--gcc/objc/objc-encoding.h74
-rw-r--r--gcc/objc/objc-gnu-runtime-abi-01.c1
-rw-r--r--gcc/objc/objc-next-runtime-abi-01.c1
-rw-r--r--gcc/objc/objc-next-runtime-abi-02.c2
-rw-r--r--gcc/objc/objc-runtime-shared-support.c1
-rw-r--r--gcc/objc/objc-runtime-shared-support.h8
11 files changed, 1122 insertions, 936 deletions
diff --git a/gcc/objc/ChangeLog b/gcc/objc/ChangeLog
index 208decc7c86..e2741977546 100644
--- a/gcc/objc/ChangeLog
+++ b/gcc/objc/ChangeLog
@@ -1,3 +1,47 @@
+2011-07-04 Nicola Pero <nicola.pero@meta-innovation.com>
+
+ Refactored encoding code into objc-encoding.h and objc-encoding.c.
+ * objc-act.c (util_obstack, util_firstobj, encode_type_qualifiers,
+ encode_type, generating_instance_variables, objc_method_parm_type,
+ objc_encoded_type_size, encode_method_prototype,
+ objc_build_encode_expr, pointee_is_readonly, encode_pointer,
+ encode_array, encode_vector, encode_aggregate_fields,
+ encode_aggregate_within, encode_next_bitfield,
+ encode_gnu_bitfield, encode_field_decl,
+ objc_v2_encode_property_attr): Moved to objc-encoding.h and
+ objc-encoding.c. No change in the actual code.
+ Include objc-encoding.h.
+ (objc_init): Added TODO.
+ (objc_build_property_setter_name): Made non-static so it can be
+ called from objc-encoding.c.
+ * objc-act.h (OBJC_ENCODE_INLINE_DEFS,
+ OBJC_ENCODE_DONT_INLINE_DEFS): Moved to objc-encoding.h.
+ * objc-runtime-shared-support.h (objc_v2_encode_property_attr,
+ encode_method_prototype, encode_field_decl,
+ generating_instance_variables): Moved to objc-encoding.h.
+ (objc_build_property_setter_name): Declare.
+ * objc-encoding.c: New.
+ * objc-encoding.h: New.
+ * objc-gnu-runtime-abi-01.c: Include objc-encoding.h.
+ * objc-next-runtime-abi-01.c: Likewise.
+ * objc-next-runtime-abi-02.c: Likewise.
+ * objc-runtime-shared-support.c: Likewise.
+ * Make-lang.in (OBJC_OBJS): Added objc-encoding.o.
+ (objc/objc-lang.o): Reordered dependencies.
+ (objc/objc-runtime-shared-support.o): Reordered dependencies.
+ Added dependencies on objc-encoding.h and on $(GGC_H),
+ $(DIAGNOSTIC_CORE_H), $(FLAGS_H) and input.h.
+ (objc/objc-gnu-runtime-abi-01.o): Likewise.
+ (objc/objc-next-runtime-abi-01.o): Likewise.
+ (objc/objc-next-runtime-abi-02.o): Likewise.
+ (objc/objc-act.o): Reordered dependencies. Added dependency on
+ objc-encoding.h.
+ (objc/objc-encoding.o): New rule.
+
+ * objc-encoding.c (encode_type): Use "%<%T%>" format when printing
+ warning "unknown type %<%T%> found during Objective-C encoding"
+ instead of using gen_type_name.
+
2011-06-05 Nicola Pero <nicola.pero@meta-innovation.com>
* objc-act.c (receiver_is_class_object): Expanded comment.
diff --git a/gcc/objc/Make-lang.in b/gcc/objc/Make-lang.in
index 357028f26ea..1ac74ba4549 100644
--- a/gcc/objc/Make-lang.in
+++ b/gcc/objc/Make-lang.in
@@ -55,6 +55,7 @@ OBJC_OBJS = objc/objc-lang.o objc/objc-act.o \
objc/objc-gnu-runtime-abi-01.o \
objc/objc-next-runtime-abi-01.o \
objc/objc-next-runtime-abi-02.o \
+ objc/objc-encoding.o
objc_OBJS = $(OBJC_OBJS) cc1obj-checksum.o
@@ -73,33 +74,75 @@ cc1obj$(exeext): $(OBJC_OBJS) $(C_AND_OBJC_OBJS) cc1obj-checksum.o $(BACKEND) $(
# Objective C language specific files.
-objc/objc-lang.o : objc/objc-lang.c $(START_HDRS) \
- $(GGC_H) $(LANGHOOKS_DEF_H) $(C_COMMON_H) gtype-objc.h \
+# When editing, please keep the objc/ header dependencies in
+# alphabetical order, and try to use a similar logical order for the
+# other files between the different targets.
+
+objc/objc-lang.o : objc/objc-lang.c \
+ $(START_HDRS) \
+ $(GGC_H) \
+ $(LANGHOOKS_DEF_H) $(C_COMMON_H) gtype-objc.h \
c-objc-common.h
objc/objc-runtime-shared-support.o : objc/objc-runtime-shared-support.c \
- $(START_HDRS) objc/objc-runtime-shared-support.h $(OBSTACK_H) \
- objc/objc-next-metadata-tags.h gt-objc-objc-runtime-shared-support.h
-
-objc/objc-gnu-runtime-abi-01.o: objc/objc-gnu-runtime-abi-01.c $(START_HDRS) \
- objc/objc-runtime-hooks.h $(GGC_H) \
- objc/objc-runtime-shared-support.h gt-objc-objc-gnu-runtime-abi-01.h toplev.h
-
-objc/objc-next-runtime-abi-01.o: objc/objc-next-runtime-abi-01.c $(START_HDRS) \
- $(GGC_H) objc/objc-runtime-hooks.h \
- objc/objc-next-metadata-tags.h gt-objc-objc-next-runtime-abi-01.h output.h \
- objc/objc-runtime-shared-support.h $(TARGET_H)
-
-objc/objc-next-runtime-abi-02.o: objc/objc-next-runtime-abi-02.c $(START_HDRS) \
- $(GGC_H) objc/objc-runtime-hooks.h \
- objc/objc-next-metadata-tags.h gt-objc-objc-next-runtime-abi-02.h $(TARGET_H) \
- objc/objc-runtime-shared-support.h $(OBSTACK_H)
-
-objc/objc-act.o : objc/objc-act.c $(START_HDRS) $(GGC_H) \
- $(DIAGNOSTIC_CORE_H) toplev.h $(FLAGS_H) input.h $(FUNCTION_H) output.h debug.h \
- $(LANGHOOKS_DEF_H) $(HASHTAB_H) $(C_PRAGMA_H) gt-objc-objc-act.h $(OBSTACK_H) \
- $(GIMPLE_H) objc/objc-runtime-shared-support.h objc/objc-runtime-hooks.h \
- $(C_TARGET_H)
+ gt-objc-objc-runtime-shared-support.h \
+ $(START_HDRS) \
+ $(GGC_H) $(DIAGNOSTIC_CORE_H) $(FLAGS_H) input.h \
+ $(OBSTACK_H) \
+ objc/objc-encoding.h \
+ objc/objc-next-metadata-tags.h \
+ objc/objc-runtime-shared-support.h
+
+objc/objc-gnu-runtime-abi-01.o: objc/objc-gnu-runtime-abi-01.c \
+ gt-objc-objc-gnu-runtime-abi-01.h \
+ $(START_HDRS) \
+ $(GGC_H) $(DIAGNOSTIC_CORE_H) $(FLAGS_H) input.h \
+ $(OBSTACK_H) \
+ toplev.h \
+ objc/objc-encoding.h \
+ objc/objc-runtime-hooks.h \
+ objc/objc-runtime-shared-support.h
+
+objc/objc-next-runtime-abi-01.o: objc/objc-next-runtime-abi-01.c \
+ gt-objc-objc-next-runtime-abi-01.h \
+ $(START_HDRS) \
+ $(GGC_H) $(DIAGNOSTIC_CORE_H) $(FLAGS_H) input.h \
+ $(OBSTACK_H) \
+ $(TARGET_H) output.h \
+ objc/objc-encoding.h \
+ objc/objc-next-metadata-tags.h \
+ objc/objc-runtime-hooks.h \
+ objc/objc-runtime-shared-support.h
+
+objc/objc-next-runtime-abi-02.o: objc/objc-next-runtime-abi-02.c \
+ gt-objc-objc-next-runtime-abi-02.h \
+ $(START_HDRS) \
+ $(GGC_H) $(DIAGNOSTIC_CORE_H) $(FLAGS_H) input.h \
+ $(OBSTACK_H) \
+ $(TARGET_H) \
+ objc/objc-encoding.h \
+ objc/objc-next-metadata-tags.h \
+ objc/objc-runtime-hooks.h \
+ objc/objc-runtime-shared-support.h
+
+objc/objc-act.o : objc/objc-act.c \
+ gt-objc-objc-act.h \
+ $(START_HDRS) \
+ $(GGC_H) $(DIAGNOSTIC_CORE_H) $(FLAGS_H) input.h \
+ $(OBSTACK_H) \
+ toplev.h $(FUNCTION_H) output.h debug.h $(LANGHOOKS_DEF_H) \
+ $(HASHTAB_H) $(GIMPLE_H) \
+ $(C_PRAGMA_H) $(C_TARGET_H) \
+ objc/objc-encoding.h \
+ objc/objc-runtime-hooks.h \
+ objc/objc-runtime-shared-support.h
+
+objc/objc-encoding.o : objc/objc-encoding.c \
+ $(START_HDRS) \
+ $(GGC_H) $(DIAGNOSTIC_CORE_H) $(FLAGS_H) input.h \
+ $(OBSTACK_H) \
+ objc/objc-encoding.h \
+ objc/objc-runtime-shared-support.h
objc.srcextra:
diff --git a/gcc/objc/objc-act.c b/gcc/objc/objc-act.c
index 321d52aaf28..14db224df75 100644
--- a/gcc/objc/objc-act.c
+++ b/gcc/objc/objc-act.c
@@ -64,6 +64,9 @@ along with GCC; see the file COPYING3. If not see
/* For enum gimplify_status */
#include "gimple.h"
+/* For encode_method_prototype(). */
+#include "objc-encoding.h"
+
static unsigned int should_call_super_dealloc = 0;
/* When building Objective-C++, we are not linking against the C front-end
@@ -105,17 +108,6 @@ static unsigned int should_call_super_dealloc = 0;
#define OBJC_FORWARDING_MIN_OFFSET 0
#endif
-/* Set up for use of obstacks. */
-
-#include "obstack.h"
-
-/* This obstack is used to accumulate the encoding of a data type. */
-struct obstack util_obstack;
-
-/* This points to the beginning of obstack contents, so we can free
- the whole contents. */
-char *util_firstobj;
-
/*** Private Interface (procedures) ***/
/* Init stuff. */
@@ -146,7 +138,6 @@ static bool objc_derived_from_p (tree, tree);
static void objc_gen_property_data (tree, tree);
static void objc_synthesize_getter (tree, tree, tree);
static void objc_synthesize_setter (tree, tree, tree);
-static char *objc_build_property_setter_name (tree);
static tree lookup_property (tree, tree);
static tree lookup_property_in_list (tree, tree);
static tree lookup_property_in_protocol_list (tree, tree);
@@ -195,11 +186,6 @@ static inline tree lookup_category (tree, tree);
static tree lookup_protocol (tree, bool, bool);
static tree lookup_and_install_protocols (tree, bool);
-/* Type encoding. */
-
-static void encode_type_qualifiers (tree);
-static void encode_type (tree, int, int);
-
#ifdef OBJCPLUS
static void really_start_method (tree, tree);
#else
@@ -279,13 +265,6 @@ static GTY((param_is (struct string_descriptor))) htab_t string_htab;
FILE *gen_declaration_file;
-/* Tells "encode_pointer/encode_aggregate" whether we are generating
- type descriptors for instance variables (as opposed to methods).
- Type descriptors for instance variables contain more information
- than methods (for static typing and embedded structures). */
-
-int generating_instance_variables = 0;
-
/* Hooks for stuff that differs between runtimes. */
objc_runtime_hooks runtime;
@@ -402,9 +381,9 @@ objc_init (void)
/* Set up stuff used by FE parser and all runtimes. */
errbuf = XNEWVEC (char, 1024 * 10);
hash_init ();
+ /* TODO: Use objc_encoding_init(). */
gcc_obstack_init (&util_obstack);
util_firstobj = (char *) obstack_finish (&util_obstack);
-
/* ... and then check flags and set-up for the selected runtime ... */
if (flag_next_runtime && flag_objc_abi >= 2)
ok = objc_next_runtime_abi_02_init (&runtime);
@@ -4451,110 +4430,6 @@ build_private_template (tree klass)
}
}
-/* Begin code generation for protocols... */
-
-static tree
-objc_method_parm_type (tree type)
-{
- type = TREE_VALUE (TREE_TYPE (type));
- if (TREE_CODE (type) == TYPE_DECL)
- type = TREE_TYPE (type);
- return type;
-}
-
-static int
-objc_encoded_type_size (tree type)
-{
- int sz = int_size_in_bytes (type);
-
- /* Make all integer and enum types at least as large
- as an int. */
- if (sz > 0 && INTEGRAL_TYPE_P (type))
- sz = MAX (sz, int_size_in_bytes (integer_type_node));
- /* Treat arrays as pointers, since that's how they're
- passed in. */
- else if (TREE_CODE (type) == ARRAY_TYPE)
- sz = int_size_in_bytes (ptr_type_node);
- return sz;
-}
-
-/* Encode a method prototype.
-
- The format is described in gcc/doc/objc.texi, section 'Method
- signatures'.
- */
-
-tree
-encode_method_prototype (tree method_decl)
-{
- tree parms;
- int parm_offset, i;
- char buf[40];
- tree result;
-
- /* ONEWAY and BYCOPY, for remote object are the only method qualifiers. */
- encode_type_qualifiers (TREE_PURPOSE (TREE_TYPE (method_decl)));
-
- /* Encode return type. */
- encode_type (objc_method_parm_type (method_decl),
- obstack_object_size (&util_obstack),
- OBJC_ENCODE_INLINE_DEFS);
-
- /* Stack size. */
- /* The first two arguments (self and _cmd) are pointers; account for
- their size. */
- i = int_size_in_bytes (ptr_type_node);
- parm_offset = 2 * i;
- for (parms = METHOD_SEL_ARGS (method_decl); parms;
- parms = DECL_CHAIN (parms))
- {
- tree type = objc_method_parm_type (parms);
- int sz = objc_encoded_type_size (type);
-
- /* If a type size is not known, bail out. */
- if (sz < 0)
- {
- error_at (DECL_SOURCE_LOCATION (method_decl),
- "type %qT does not have a known size",
- type);
- /* Pretend that the encoding succeeded; the compilation will
- fail nevertheless. */
- goto finish_encoding;
- }
- parm_offset += sz;
- }
-
- sprintf (buf, "%d@0:%d", parm_offset, i);
- obstack_grow (&util_obstack, buf, strlen (buf));
-
- /* Argument types. */
- parm_offset = 2 * i;
- for (parms = METHOD_SEL_ARGS (method_decl); parms;
- parms = DECL_CHAIN (parms))
- {
- tree type = objc_method_parm_type (parms);
-
- /* Process argument qualifiers for user supplied arguments. */
- encode_type_qualifiers (TREE_PURPOSE (TREE_TYPE (parms)));
-
- /* Type. */
- encode_type (type, obstack_object_size (&util_obstack),
- OBJC_ENCODE_INLINE_DEFS);
-
- /* Compute offset. */
- sprintf (buf, "%d", parm_offset);
- parm_offset += objc_encoded_type_size (type);
-
- obstack_grow (&util_obstack, buf, strlen (buf));
- }
-
- finish_encoding:
- obstack_1grow (&util_obstack, '\0');
- result = get_identifier (XOBFINISH (&util_obstack, char *));
- obstack_free (&util_obstack, util_firstobj);
- return result;
-}
-
/* Generate either '- .cxx_construct' or '- .cxx_destruct' for the
current class. */
#ifdef OBJCPLUS
@@ -5864,25 +5739,6 @@ objc_build_selector_expr (location_t loc, tree selnamelist)
return (*runtime.build_selector_reference) (loc, selname, NULL_TREE);
}
-/* This is used to implement @encode(). See gcc/doc/objc.texi,
- section '@encode'. */
-tree
-objc_build_encode_expr (tree type)
-{
- tree result;
- const char *string;
-
- encode_type (type, obstack_object_size (&util_obstack),
- OBJC_ENCODE_INLINE_DEFS);
- obstack_1grow (&util_obstack, 0); /* null terminate string */
- string = XOBFINISH (&util_obstack, const char *);
-
- /* Synthesize a string that represents the encoded struct/union. */
- result = my_build_string (strlen (string) + 1, string);
- obstack_free (&util_obstack, util_firstobj);
- return result;
-}
-
static tree
build_ivar_reference (tree id)
{
@@ -7308,7 +7164,7 @@ continue_class (tree klass)
}
/* This routine builds name of the setter synthesized function. */
-static char *
+char *
objc_build_property_setter_name (tree ident)
{
/* TODO: Use alloca to allocate buffer of appropriate size. */
@@ -10306,758 +10162,6 @@ objc_check_format_arg (tree ARG_UNUSED (format_arg),
{
}
-/* --- Encode --- */
-/* "Encode" a data type into a string, which grows in util_obstack.
-
- The format is described in gcc/doc/objc.texi, section 'Type
- encoding'.
-
- Most of the encode_xxx functions have a 'type' argument, which is
- the type to encode, and an integer 'curtype' argument, which is the
- index in the encoding string of the beginning of the encoding of
- the current type, and allows you to find what characters have
- already been written for the current type (they are the ones in the
- current encoding string starting from 'curtype').
-
- For example, if we are encoding a method which returns 'int' and
- takes a 'char **' argument, then when we get to the point of
- encoding the 'char **' argument, the encoded string already
- contains 'i12@0:4' (assuming a pointer size of 4 bytes). So,
- 'curtype' will be set to 7 when starting to encode 'char **'.
- During the whole of the encoding of 'char **', 'curtype' will be
- fixed at 7, so the routine encoding the second pointer can find out
- that it's actually encoding a pointer to a pointer by looking
- backwards at what has already been encoded for the current type,
- and seeing there is a "^" (meaning a pointer) in there.
-*/
-
-
-/* Encode type qualifiers encodes one of the "PQ" Objective-C
- keywords, ie 'in', 'out', 'inout', 'bycopy', 'byref', 'oneway'.
- 'const', instead, is encoded directly as part of the type.
- */
-
-static void
-encode_type_qualifiers (tree declspecs)
-{
- tree spec;
-
- for (spec = declspecs; spec; spec = TREE_CHAIN (spec))
- {
- /* FIXME: Shouldn't we use token->keyword here ? */
- if (ridpointers[(int) RID_IN] == TREE_VALUE (spec))
- obstack_1grow (&util_obstack, 'n');
- else if (ridpointers[(int) RID_INOUT] == TREE_VALUE (spec))
- obstack_1grow (&util_obstack, 'N');
- else if (ridpointers[(int) RID_OUT] == TREE_VALUE (spec))
- obstack_1grow (&util_obstack, 'o');
- else if (ridpointers[(int) RID_BYCOPY] == TREE_VALUE (spec))
- obstack_1grow (&util_obstack, 'O');
- else if (ridpointers[(int) RID_BYREF] == TREE_VALUE (spec))
- obstack_1grow (&util_obstack, 'R');
- else if (ridpointers[(int) RID_ONEWAY] == TREE_VALUE (spec))
- obstack_1grow (&util_obstack, 'V');
- else
- gcc_unreachable ();
- }
-}
-
-/* Determine if a pointee is marked read-only. Only used by the NeXT
- runtime to be compatible with gcc-3.3. */
-
-static bool
-pointee_is_readonly (tree pointee)
-{
- while (POINTER_TYPE_P (pointee))
- pointee = TREE_TYPE (pointee);
-
- return TYPE_READONLY (pointee);
-}
-
-/* Encode a pointer type. */
-
-static void
-encode_pointer (tree type, int curtype, int format)
-{
- tree pointer_to = TREE_TYPE (type);
-
- if (flag_next_runtime)
- {
- /* This code is used to be compatible with gcc-3.3. */
- /* For historical/compatibility reasons, the read-only qualifier
- of the pointee gets emitted _before_ the '^'. The read-only
- qualifier of the pointer itself gets ignored, _unless_ we are
- looking at a typedef! Also, do not emit the 'r' for anything
- but the outermost type! */
- if (!generating_instance_variables
- && (obstack_object_size (&util_obstack) - curtype <= 1)
- && (TYPE_NAME (type) && TREE_CODE (TYPE_NAME (type)) == TYPE_DECL
- ? TYPE_READONLY (type)
- : pointee_is_readonly (pointer_to)))
- obstack_1grow (&util_obstack, 'r');
- }
-
- if (TREE_CODE (pointer_to) == RECORD_TYPE)
- {
- if (OBJC_TYPE_NAME (pointer_to)
- && TREE_CODE (OBJC_TYPE_NAME (pointer_to)) == IDENTIFIER_NODE)
- {
- const char *name = IDENTIFIER_POINTER (OBJC_TYPE_NAME (pointer_to));
-
- if (strcmp (name, TAG_OBJECT) == 0) /* '@' */
- {
- obstack_1grow (&util_obstack, '@');
- return;
- }
- else if (TYPE_HAS_OBJC_INFO (pointer_to)
- && TYPE_OBJC_INTERFACE (pointer_to))
- {
- if (generating_instance_variables)
- {
- obstack_1grow (&util_obstack, '@');
- obstack_1grow (&util_obstack, '"');
- obstack_grow (&util_obstack, name, strlen (name));
- obstack_1grow (&util_obstack, '"');
- return;
- }
- else
- {
- obstack_1grow (&util_obstack, '@');
- return;
- }
- }
- else if (strcmp (name, TAG_CLASS) == 0) /* '#' */
- {
- obstack_1grow (&util_obstack, '#');
- return;
- }
- else if (strcmp (name, TAG_SELECTOR) == 0) /* ':' */
- {
- obstack_1grow (&util_obstack, ':');
- return;
- }
- }
- }
- else if (TREE_CODE (pointer_to) == INTEGER_TYPE
- && TYPE_MODE (pointer_to) == QImode)
- {
- tree pname = TREE_CODE (OBJC_TYPE_NAME (pointer_to)) == IDENTIFIER_NODE
- ? OBJC_TYPE_NAME (pointer_to)
- : DECL_NAME (OBJC_TYPE_NAME (pointer_to));
-
- /* (BOOL *) are an exception and are encoded as ^c, while all
- other pointers to char are encoded as *. */
- if (strcmp (IDENTIFIER_POINTER (pname), "BOOL"))
- {
- if (!flag_next_runtime)
- {
- /* The NeXT runtime adds the 'r' before getting here. */
-
- /* It appears that "r*" means "const char *" rather than
- "char *const". "char *const" is encoded as "*",
- which is identical to "char *", so the "const" is
- unfortunately lost. */
- if (TYPE_READONLY (pointer_to))
- obstack_1grow (&util_obstack, 'r');
- }
-
- obstack_1grow (&util_obstack, '*');
- return;
- }
- }
-
- /* We have a normal pointer type that does not get special treatment. */
- obstack_1grow (&util_obstack, '^');
- encode_type (pointer_to, curtype, format);
-}
-
-static void
-encode_array (tree type, int curtype, int format)
-{
- tree an_int_cst = TYPE_SIZE (type);
- tree array_of = TREE_TYPE (type);
- char buffer[40];
-
- if (an_int_cst == NULL)
- {
- /* We are trying to encode an incomplete array. An incomplete
- array is forbidden as part of an instance variable; but it
- may occur if the instance variable is a pointer to such an
- array. */
-
- /* So the only case in which an incomplete array could occur
- (without being pointed to) is if we are encoding the
- arguments or return value of a method. In that case, an
- incomplete array argument or return value (eg,
- -(void)display: (char[])string) is treated like a pointer
- because that is how the compiler does the function call. A
- special, more complicated case, is when the incomplete array
- is the last member of a struct (eg, if we are encoding
- "struct { unsigned long int a;double b[];}"), which is again
- part of a method argument/return value. In that case, we
- really need to communicate to the runtime that there is an
- incomplete array (not a pointer!) there. So, we detect that
- special case and encode it as a zero-length array.
-
- Try to detect that we are part of a struct. We do this by
- searching for '=' in the type encoding for the current type.
- NB: This hack assumes that you can't use '=' as part of a C
- identifier.
- */
- {
- char *enc = obstack_base (&util_obstack) + curtype;
- if (memchr (enc, '=',
- obstack_object_size (&util_obstack) - curtype) == NULL)
- {
- /* We are not inside a struct. Encode the array as a
- pointer. */
- encode_pointer (type, curtype, format);
- return;
- }
- }
-
- /* Else, we are in a struct, and we encode it as a zero-length
- array. */
- sprintf (buffer, "[" HOST_WIDE_INT_PRINT_DEC, (HOST_WIDE_INT)0);
- }
- else if (TREE_INT_CST_LOW (TYPE_SIZE (array_of)) == 0)
- sprintf (buffer, "[" HOST_WIDE_INT_PRINT_DEC, (HOST_WIDE_INT)0);
- else
- sprintf (buffer, "[" HOST_WIDE_INT_PRINT_DEC,
- TREE_INT_CST_LOW (an_int_cst)
- / TREE_INT_CST_LOW (TYPE_SIZE (array_of)));
-
- obstack_grow (&util_obstack, buffer, strlen (buffer));
- encode_type (array_of, curtype, format);
- obstack_1grow (&util_obstack, ']');
- return;
-}
-
-/* Encode a vector. The vector type is a GCC extension to C. */
-static void
-encode_vector (tree type, int curtype, int format)
-{
- tree vector_of = TREE_TYPE (type);
- char buffer[40];
-
- /* Vectors are like simple fixed-size arrays. */
-
- /* Output ![xx,yy,<code>] where xx is the vector_size, yy is the
- alignment of the vector, and <code> is the base type. Eg, int
- __attribute__ ((vector_size (16))) gets encoded as ![16,32,i]
- assuming that the alignment is 32 bytes. We include size and
- alignment in bytes so that the runtime does not have to have any
- knowledge of the actual types.
- */
- sprintf (buffer, "![" HOST_WIDE_INT_PRINT_DEC ",%d",
- /* We want to compute the equivalent of sizeof (<vector>).
- Code inspired by c_sizeof_or_alignof_type. */
- ((TREE_INT_CST_LOW (TYPE_SIZE_UNIT (type))
- / (TYPE_PRECISION (char_type_node) / BITS_PER_UNIT))),
- /* We want to compute the equivalent of __alignof__
- (<vector>). Code inspired by
- c_sizeof_or_alignof_type. */
- TYPE_ALIGN_UNIT (type));
- obstack_grow (&util_obstack, buffer, strlen (buffer));
- encode_type (vector_of, curtype, format);
- obstack_1grow (&util_obstack, ']');
- return;
-}
-
-static void
-encode_aggregate_fields (tree type, bool pointed_to, int curtype, int format)
-{
- tree field = TYPE_FIELDS (type);
-
- for (; field; field = DECL_CHAIN (field))
- {
-#ifdef OBJCPLUS
- /* C++ static members, and things that are not field at all,
- should not appear in the encoding. */
- if (TREE_CODE (field) != FIELD_DECL || TREE_STATIC (field))
- continue;
-#endif
-
- /* Recursively encode fields of embedded base classes. */
- if (DECL_ARTIFICIAL (field) && !DECL_NAME (field)
- && TREE_CODE (TREE_TYPE (field)) == RECORD_TYPE)
- {
- encode_aggregate_fields (TREE_TYPE (field),
- pointed_to, curtype, format);
- continue;
- }
-
- if (generating_instance_variables && !pointed_to)
- {
- tree fname = DECL_NAME (field);
-
- obstack_1grow (&util_obstack, '"');
-
- if (fname && TREE_CODE (fname) == IDENTIFIER_NODE)
- obstack_grow (&util_obstack,
- IDENTIFIER_POINTER (fname),
- strlen (IDENTIFIER_POINTER (fname)));
-
- obstack_1grow (&util_obstack, '"');
- }
-
- encode_field_decl (field, curtype, format);
- }
-}
-
-static void
-encode_aggregate_within (tree type, int curtype, int format, int left,
- int right)
-{
- tree name;
- /* NB: aggregates that are pointed to have slightly different encoding
- rules in that you never encode the names of instance variables. */
- int ob_size = obstack_object_size (&util_obstack);
- bool inline_contents = false;
- bool pointed_to = false;
-
- if (flag_next_runtime)
- {
- if (ob_size > 0 && *(obstack_next_free (&util_obstack) - 1) == '^')
- pointed_to = true;
-
- if ((format == OBJC_ENCODE_INLINE_DEFS || generating_instance_variables)
- && (!pointed_to || ob_size - curtype == 1
- || (ob_size - curtype == 2
- && *(obstack_next_free (&util_obstack) - 2) == 'r')))
- inline_contents = true;
- }
- else
- {
- /* c0 and c1 are the last two characters in the encoding of the
- current type; if the last two characters were '^' or '^r',
- then we are encoding an aggregate that is "pointed to". The
- comment above applies: in that case we should avoid encoding
- the names of instance variables.
- */
- char c1 = ob_size > 1 ? *(obstack_next_free (&util_obstack) - 2) : 0;
- char c0 = ob_size > 0 ? *(obstack_next_free (&util_obstack) - 1) : 0;
-
- if (c0 == '^' || (c1 == '^' && c0 == 'r'))
- pointed_to = true;
-
- if (format == OBJC_ENCODE_INLINE_DEFS || generating_instance_variables)
- {
- if (!pointed_to)
- inline_contents = true;
- else
- {
- /* Note that the check (ob_size - curtype < 2) prevents
- infinite recursion when encoding a structure which is
- a linked list (eg, struct node { struct node *next;
- }). Each time we follow a pointer, we add one
- character to ob_size, and curtype is fixed, so after
- at most two pointers we stop inlining contents and
- break the loop.
-
- The other case where we don't inline is "^r", which
- is a pointer to a constant struct.
- */
- if ((ob_size - curtype <= 2) && !(c0 == 'r'))
- inline_contents = true;
- }
- }
- }
-
- /* Traverse struct aliases; it is important to get the
- original struct and its tag name (if any). */
- type = TYPE_MAIN_VARIANT (type);
- name = OBJC_TYPE_NAME (type);
- /* Open parenth/bracket. */
- obstack_1grow (&util_obstack, left);
-
- /* Encode the struct/union tag name, or '?' if a tag was
- not provided. Typedef aliases do not qualify. */
-#ifdef OBJCPLUS
- /* For compatibility with the NeXT runtime, ObjC++ encodes template
- args as a composite struct tag name. */
- if (name && TREE_CODE (name) == IDENTIFIER_NODE
- /* Did this struct have a tag? */
- && !TYPE_WAS_ANONYMOUS (type))
- obstack_grow (&util_obstack,
- decl_as_string (type, TFF_DECL_SPECIFIERS | TFF_UNQUALIFIED_NAME),
- strlen (decl_as_string (type, TFF_DECL_SPECIFIERS | TFF_UNQUALIFIED_NAME)));
-#else
- if (name && TREE_CODE (name) == IDENTIFIER_NODE)
- obstack_grow (&util_obstack,
- IDENTIFIER_POINTER (name),
- strlen (IDENTIFIER_POINTER (name)));
-#endif
- else
- obstack_1grow (&util_obstack, '?');
-
- /* Encode the types (and possibly names) of the inner fields,
- if required. */
- if (inline_contents)
- {
- obstack_1grow (&util_obstack, '=');
- encode_aggregate_fields (type, pointed_to, curtype, format);
- }
- /* Close parenth/bracket. */
- obstack_1grow (&util_obstack, right);
-}
-
-/* Encode a bitfield NeXT-style (i.e., without a bit offset or the underlying
- field type. */
-
-static void
-encode_next_bitfield (int width)
-{
- char buffer[40];
- sprintf (buffer, "b%d", width);
- obstack_grow (&util_obstack, buffer, strlen (buffer));
-}
-
-/* Encodes 'type', ignoring type qualifiers (which you should encode
- beforehand if needed) with the exception of 'const', which is
- encoded by encode_type. See above for the explanation of
- 'curtype'. 'format' can be OBJC_ENCODE_INLINE_DEFS or
- OBJC_ENCODE_DONT_INLINE_DEFS.
-*/
-static void
-encode_type (tree type, int curtype, int format)
-{
- enum tree_code code = TREE_CODE (type);
-
- /* Ignore type qualifiers other than 'const' when encoding a
- type. */
-
- if (type == error_mark_node)
- return;
-
- if (!flag_next_runtime)
- {
- if (TYPE_READONLY (type))
- obstack_1grow (&util_obstack, 'r');
- }
-
- switch (code)
- {
- case ENUMERAL_TYPE:
- if (flag_next_runtime)
- {
- /* Kludge for backwards-compatibility with gcc-3.3: enums
- are always encoded as 'i' no matter what type they
- actually are (!). */
- obstack_1grow (&util_obstack, 'i');
- break;
- }
- /* Else, they are encoded exactly like the integer type that is
- used by the compiler to store them. */
- case INTEGER_TYPE:
- {
- char c;
- switch (GET_MODE_BITSIZE (TYPE_MODE (type)))
- {
- case 8: c = TYPE_UNSIGNED (type) ? 'C' : 'c'; break;
- case 16: c = TYPE_UNSIGNED (type) ? 'S' : 's'; break;
- case 32:
- {
- tree int_type = type;
- if (flag_next_runtime)
- {
- /* Another legacy kludge for compatiblity with
- gcc-3.3: 32-bit longs are encoded as 'l' or 'L',
- but not always. For typedefs, we need to use 'i'
- or 'I' instead if encoding a struct field, or a
- pointer! */
- int_type = ((!generating_instance_variables
- && (obstack_object_size (&util_obstack)
- == (unsigned) curtype))
- ? TYPE_MAIN_VARIANT (type)
- : type);
- }
- if (int_type == long_unsigned_type_node
- || int_type == long_integer_type_node)
- c = TYPE_UNSIGNED (type) ? 'L' : 'l';
- else
- c = TYPE_UNSIGNED (type) ? 'I' : 'i';
- }
- break;
- case 64: c = TYPE_UNSIGNED (type) ? 'Q' : 'q'; break;
- case 128: c = TYPE_UNSIGNED (type) ? 'T' : 't'; break;
- default: gcc_unreachable ();
- }
- obstack_1grow (&util_obstack, c);
- break;
- }
- case REAL_TYPE:
- {
- char c;
- /* Floating point types. */
- switch (GET_MODE_BITSIZE (TYPE_MODE (type)))
- {
- case 32: c = 'f'; break;
- case 64: c = 'd'; break;
- case 96:
- case 128: c = 'D'; break;
- default: gcc_unreachable ();
- }
- obstack_1grow (&util_obstack, c);
- break;
- }
- case VOID_TYPE:
- obstack_1grow (&util_obstack, 'v');
- break;
-
- case BOOLEAN_TYPE:
- obstack_1grow (&util_obstack, 'B');
- break;
-
- case ARRAY_TYPE:
- encode_array (type, curtype, format);
- break;
-
- case POINTER_TYPE:
-#ifdef OBJCPLUS
- case REFERENCE_TYPE:
-#endif
- encode_pointer (type, curtype, format);
- break;
-
- case RECORD_TYPE:
- encode_aggregate_within (type, curtype, format, '{', '}');
- break;
-
- case UNION_TYPE:
- encode_aggregate_within (type, curtype, format, '(', ')');
- break;
-
- case FUNCTION_TYPE: /* '?' means an unknown type. */
- obstack_1grow (&util_obstack, '?');
- break;
-
- case COMPLEX_TYPE:
- /* A complex is encoded as 'j' followed by the inner type (eg,
- "_Complex int" is encoded as 'ji'). */
- obstack_1grow (&util_obstack, 'j');
- encode_type (TREE_TYPE (type), curtype, format);
- break;
-
- case VECTOR_TYPE:
- encode_vector (type, curtype, format);
- break;
-
- default:
- warning (0, "unknown type %s found during Objective-C encoding",
- gen_type_name (type));
- obstack_1grow (&util_obstack, '?');
- break;
- }
-
- if (flag_next_runtime)
- {
- /* Super-kludge. Some ObjC qualifier and type combinations need
- to be rearranged for compatibility with gcc-3.3. */
- if (code == POINTER_TYPE && obstack_object_size (&util_obstack) >= 3)
- {
- char *enc = obstack_base (&util_obstack) + curtype;
-
- /* Rewrite "in const" from "nr" to "rn". */
- if (curtype >= 1 && !strncmp (enc - 1, "nr", 2))
- strncpy (enc - 1, "rn", 2);
- }
- }
-}
-
-static void
-encode_gnu_bitfield (int position, tree type, int size)
-{
- enum tree_code code = TREE_CODE (type);
- char buffer[40];
- char charType = '?';
-
- /* This code is only executed for the GNU runtime, so we can ignore
- the NeXT runtime kludge of always encoding enums as 'i' no matter
- what integers they actually are. */
- if (code == INTEGER_TYPE || code == ENUMERAL_TYPE)
- {
- if (integer_zerop (TYPE_MIN_VALUE (type)))
- /* Unsigned integer types. */
- {
- switch (TYPE_MODE (type))
- {
- case QImode:
- charType = 'C'; break;
- case HImode:
- charType = 'S'; break;
- case SImode:
- {
- if (type == long_unsigned_type_node)
- charType = 'L';
- else
- charType = 'I';
- break;
- }
- case DImode:
- charType = 'Q'; break;
- default:
- gcc_unreachable ();
- }
- }
- else
- /* Signed integer types. */
- {
- switch (TYPE_MODE (type))
- {
- case QImode:
- charType = 'c'; break;
- case HImode:
- charType = 's'; break;
- case SImode:
- {
- if (type == long_integer_type_node)
- charType = 'l';
- else
- charType = 'i';
- break;
- }
- case DImode:
- charType = 'q'; break;
- default:
- gcc_unreachable ();
- }
- }
- }
- else
- {
- /* Do not do any encoding, produce an error and keep going. */
- error ("trying to encode non-integer type as a bitfield");
- return;
- }
-
- sprintf (buffer, "b%d%c%d", position, charType, size);
- obstack_grow (&util_obstack, buffer, strlen (buffer));
-}
-
-void
-encode_field_decl (tree field_decl, int curtype, int format)
-{
-#ifdef OBJCPLUS
- /* C++ static members, and things that are not fields at all,
- should not appear in the encoding. */
- if (TREE_CODE (field_decl) != FIELD_DECL || TREE_STATIC (field_decl))
- return;
-#endif
-
- /* Generate the bitfield typing information, if needed. Note the difference
- between GNU and NeXT runtimes. */
- if (DECL_BIT_FIELD_TYPE (field_decl))
- {
- int size = tree_low_cst (DECL_SIZE (field_decl), 1);
-
- if (flag_next_runtime)
- encode_next_bitfield (size);
- else
- encode_gnu_bitfield (int_bit_position (field_decl),
- DECL_BIT_FIELD_TYPE (field_decl), size);
- }
- else
- encode_type (TREE_TYPE (field_decl), curtype, format);
-}
-
-/* This routine encodes the attribute of the input PROPERTY according
- to following formula:
-
- Property attributes are stored as a comma-delimited C string.
- Simple attributes such as readonly are encoded as single
- character. The parametrized attributes, getter=name and
- setter=name, are encoded as a single character followed by an
- identifier. Property types are also encoded as a parametrized
- attribute. The characters used to encode these attributes are
- defined by the following enumeration:
-
- enum PropertyAttributes {
- kPropertyReadOnly = 'R',
- kPropertyBycopy = 'C',
- kPropertyByref = '&',
- kPropertyDynamic = 'D',
- kPropertyGetter = 'G',
- kPropertySetter = 'S',
- kPropertyInstanceVariable = 'V',
- kPropertyType = 'T',
- kPropertyWeak = 'W',
- kPropertyStrong = 'P',
- kPropertyNonAtomic = 'N'
- }; */
-tree
-objc_v2_encode_prop_attr (tree property)
-{
- const char *string;
- tree type = TREE_TYPE (property);
-
- obstack_1grow (&util_obstack, 'T');
- encode_type (type, obstack_object_size (&util_obstack),
- OBJC_ENCODE_INLINE_DEFS);
-
- if (PROPERTY_READONLY (property))
- obstack_grow (&util_obstack, ",R", 2);
-
- switch (PROPERTY_ASSIGN_SEMANTICS (property))
- {
- case OBJC_PROPERTY_COPY:
- obstack_grow (&util_obstack, ",C", 2);
- break;
- case OBJC_PROPERTY_RETAIN:
- obstack_grow (&util_obstack, ",&", 2);
- break;
- case OBJC_PROPERTY_ASSIGN:
- default:
- break;
- }
-
- if (PROPERTY_DYNAMIC (property))
- obstack_grow (&util_obstack, ",D", 2);
-
- if (PROPERTY_NONATOMIC (property))
- obstack_grow (&util_obstack, ",N", 2);
-
- /* Here we want to encode the getter name, but only if it's not the
- standard one. */
- if (PROPERTY_GETTER_NAME (property) != PROPERTY_NAME (property))
- {
- obstack_grow (&util_obstack, ",G", 2);
- string = IDENTIFIER_POINTER (PROPERTY_GETTER_NAME (property));
- obstack_grow (&util_obstack, string, strlen (string));
- }
-
- if (!PROPERTY_READONLY (property))
- {
- /* Here we want to encode the setter name, but only if it's not
- the standard one. */
- tree standard_setter = get_identifier (objc_build_property_setter_name (PROPERTY_NAME (property)));
- if (PROPERTY_SETTER_NAME (property) != standard_setter)
- {
- obstack_grow (&util_obstack, ",S", 2);
- string = IDENTIFIER_POINTER (PROPERTY_SETTER_NAME (property));
- obstack_grow (&util_obstack, string, strlen (string));
- }
- }
-
- /* TODO: Encode strong ('P'), weak ('W') for garbage collection. */
-
- if (!PROPERTY_DYNAMIC (property))
- {
- obstack_grow (&util_obstack, ",V", 2);
- if (PROPERTY_IVAR_NAME (property))
- string = IDENTIFIER_POINTER (PROPERTY_IVAR_NAME (property));
- else
- string = IDENTIFIER_POINTER (PROPERTY_NAME (property));
- obstack_grow (&util_obstack, string, strlen (string));
- }
-
- /* NULL-terminate string. */
- obstack_1grow (&util_obstack, 0);
- string = XOBFINISH (&util_obstack, char *);
- obstack_free (&util_obstack, util_firstobj);
- return get_identifier (string);
-}
-
void
objc_common_init_ts (void)
{
diff --git a/gcc/objc/objc-act.h b/gcc/objc/objc-act.h
index 99551a80256..33f90fdb785 100644
--- a/gcc/objc/objc-act.h
+++ b/gcc/objc/objc-act.h
@@ -642,10 +642,6 @@ typedef enum string_section
#define METHOD_DEF 0
#define METHOD_REF 1
-/* (Decide if these can ever be validly changed.) */
-#define OBJC_ENCODE_INLINE_DEFS 0
-#define OBJC_ENCODE_DONT_INLINE_DEFS 1
-
#define BUFSIZE 1024
#define CLS_FACTORY 0x0001L
diff --git a/gcc/objc/objc-encoding.c b/gcc/objc/objc-encoding.c
new file mode 100644
index 00000000000..cb1d0c4e992
--- /dev/null
+++ b/gcc/objc/objc-encoding.c
@@ -0,0 +1,926 @@
+/* Routines dealing with ObjC encoding of types
+ Copyright (C) 1992, 1993, 1994, 1995, 1997, 1998, 1999, 2000, 2001,
+ 2002, 2003, 2004, 2005, 2007, 2008, 2009, 2010, 2011
+ Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 3, or (at your option)
+any later version.
+
+GCC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3. If not see
+<http://www.gnu.org/licenses/>. */
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "tree.h"
+
+#ifdef OBJCPLUS
+#include "cp-tree.h"
+#else
+#include "c-tree.h"
+#include "c-lang.h"
+#endif
+
+#include "c-family/c-common.h"
+#include "c-family/c-objc.h"
+
+#include "objc-encoding.h"
+#include "objc-act.h"
+
+/* For my_build_string(). */
+#include "objc-runtime-shared-support.h"
+
+/* For BITS_PER_UNIT. */
+#include "tm.h"
+
+/* When building Objective-C++, we are not linking against the C front-end
+ and so need to replicate the C tree-construction functions in some way. */
+#ifdef OBJCPLUS
+#define OBJCP_REMAP_FUNCTIONS
+#include "objcp-decl.h"
+#endif /* OBJCPLUS */
+
+/* Set up for use of obstacks. */
+#include "obstack.h"
+
+/* This obstack is used to accumulate the encoding of a data type.
+ TODO: Make this static. */
+struct obstack util_obstack;
+
+/* This points to the beginning of obstack contents, so we can free
+ the whole contents. TODO: Make this static. */
+char *util_firstobj;
+
+int generating_instance_variables = 0;
+
+static void encode_type_qualifiers (tree);
+static void encode_type (tree, int, int);
+
+static tree
+objc_method_parm_type (tree type)
+{
+ type = TREE_VALUE (TREE_TYPE (type));
+ if (TREE_CODE (type) == TYPE_DECL)
+ type = TREE_TYPE (type);
+ return type;
+}
+
+static int
+objc_encoded_type_size (tree type)
+{
+ int sz = int_size_in_bytes (type);
+
+ /* Make all integer and enum types at least as large
+ as an int. */
+ if (sz > 0 && INTEGRAL_TYPE_P (type))
+ sz = MAX (sz, int_size_in_bytes (integer_type_node));
+ /* Treat arrays as pointers, since that's how they're
+ passed in. */
+ else if (TREE_CODE (type) == ARRAY_TYPE)
+ sz = int_size_in_bytes (ptr_type_node);
+ return sz;
+}
+
+/* Encode a method prototype. */
+tree
+encode_method_prototype (tree method_decl)
+{
+ tree parms;
+ int parm_offset, i;
+ char buf[40];
+ tree result;
+
+ /* ONEWAY and BYCOPY, for remote object are the only method qualifiers. */
+ encode_type_qualifiers (TREE_PURPOSE (TREE_TYPE (method_decl)));
+
+ /* Encode return type. */
+ encode_type (objc_method_parm_type (method_decl),
+ obstack_object_size (&util_obstack),
+ OBJC_ENCODE_INLINE_DEFS);
+
+ /* Stack size. */
+ /* The first two arguments (self and _cmd) are pointers; account for
+ their size. */
+ i = int_size_in_bytes (ptr_type_node);
+ parm_offset = 2 * i;
+ for (parms = METHOD_SEL_ARGS (method_decl); parms;
+ parms = DECL_CHAIN (parms))
+ {
+ tree type = objc_method_parm_type (parms);
+ int sz = objc_encoded_type_size (type);
+
+ /* If a type size is not known, bail out. */
+ if (sz < 0)
+ {
+ error_at (DECL_SOURCE_LOCATION (method_decl),
+ "type %qT does not have a known size",
+ type);
+ /* Pretend that the encoding succeeded; the compilation will
+ fail nevertheless. */
+ goto finish_encoding;
+ }
+ parm_offset += sz;
+ }
+
+ sprintf (buf, "%d@0:%d", parm_offset, i);
+ obstack_grow (&util_obstack, buf, strlen (buf));
+
+ /* Argument types. */
+ parm_offset = 2 * i;
+ for (parms = METHOD_SEL_ARGS (method_decl); parms;
+ parms = DECL_CHAIN (parms))
+ {
+ tree type = objc_method_parm_type (parms);
+
+ /* Process argument qualifiers for user supplied arguments. */
+ encode_type_qualifiers (TREE_PURPOSE (TREE_TYPE (parms)));
+
+ /* Type. */
+ encode_type (type, obstack_object_size (&util_obstack),
+ OBJC_ENCODE_INLINE_DEFS);
+
+ /* Compute offset. */
+ sprintf (buf, "%d", parm_offset);
+ parm_offset += objc_encoded_type_size (type);
+
+ obstack_grow (&util_obstack, buf, strlen (buf));
+ }
+
+ finish_encoding:
+ obstack_1grow (&util_obstack, '\0');
+ result = get_identifier (XOBFINISH (&util_obstack, char *));
+ obstack_free (&util_obstack, util_firstobj);
+ return result;
+}
+
+/* This is used to implement @encode(). */
+tree
+objc_build_encode_expr (tree type)
+{
+ tree result;
+ const char *string;
+
+ encode_type (type, obstack_object_size (&util_obstack),
+ OBJC_ENCODE_INLINE_DEFS);
+ obstack_1grow (&util_obstack, 0); /* null terminate string */
+ string = XOBFINISH (&util_obstack, const char *);
+
+ /* Synthesize a string that represents the encoded struct/union. */
+ result = my_build_string (strlen (string) + 1, string);
+ obstack_free (&util_obstack, util_firstobj);
+ return result;
+}
+
+/* "Encode" a data type into a string, which grows in util_obstack.
+
+ The format is described in gcc/doc/objc.texi, section 'Type
+ encoding'.
+
+ Most of the encode_xxx functions have a 'type' argument, which is
+ the type to encode, and an integer 'curtype' argument, which is the
+ index in the encoding string of the beginning of the encoding of
+ the current type, and allows you to find what characters have
+ already been written for the current type (they are the ones in the
+ current encoding string starting from 'curtype').
+
+ For example, if we are encoding a method which returns 'int' and
+ takes a 'char **' argument, then when we get to the point of
+ encoding the 'char **' argument, the encoded string already
+ contains 'i12@0:4' (assuming a pointer size of 4 bytes). So,
+ 'curtype' will be set to 7 when starting to encode 'char **'.
+ During the whole of the encoding of 'char **', 'curtype' will be
+ fixed at 7, so the routine encoding the second pointer can find out
+ that it's actually encoding a pointer to a pointer by looking
+ backwards at what has already been encoded for the current type,
+ and seeing there is a "^" (meaning a pointer) in there. */
+
+
+/* Encode type qualifiers encodes one of the "PQ" Objective-C
+ keywords, ie 'in', 'out', 'inout', 'bycopy', 'byref', 'oneway'.
+ 'const', instead, is encoded directly as part of the type. */
+static void
+encode_type_qualifiers (tree declspecs)
+{
+ tree spec;
+
+ for (spec = declspecs; spec; spec = TREE_CHAIN (spec))
+ {
+ /* FIXME: Shouldn't we use token->keyword here ? */
+ if (ridpointers[(int) RID_IN] == TREE_VALUE (spec))
+ obstack_1grow (&util_obstack, 'n');
+ else if (ridpointers[(int) RID_INOUT] == TREE_VALUE (spec))
+ obstack_1grow (&util_obstack, 'N');
+ else if (ridpointers[(int) RID_OUT] == TREE_VALUE (spec))
+ obstack_1grow (&util_obstack, 'o');
+ else if (ridpointers[(int) RID_BYCOPY] == TREE_VALUE (spec))
+ obstack_1grow (&util_obstack, 'O');
+ else if (ridpointers[(int) RID_BYREF] == TREE_VALUE (spec))
+ obstack_1grow (&util_obstack, 'R');
+ else if (ridpointers[(int) RID_ONEWAY] == TREE_VALUE (spec))
+ obstack_1grow (&util_obstack, 'V');
+ else
+ gcc_unreachable ();
+ }
+}
+
+/* Determine if a pointee is marked read-only. Only used by the NeXT
+ runtime to be compatible with gcc-3.3. */
+static bool
+pointee_is_readonly (tree pointee)
+{
+ while (POINTER_TYPE_P (pointee))
+ pointee = TREE_TYPE (pointee);
+
+ return TYPE_READONLY (pointee);
+}
+
+/* Encode a pointer type. */
+static void
+encode_pointer (tree type, int curtype, int format)
+{
+ tree pointer_to = TREE_TYPE (type);
+
+ if (flag_next_runtime)
+ {
+ /* This code is used to be compatible with gcc-3.3. */
+ /* For historical/compatibility reasons, the read-only qualifier
+ of the pointee gets emitted _before_ the '^'. The read-only
+ qualifier of the pointer itself gets ignored, _unless_ we are
+ looking at a typedef! Also, do not emit the 'r' for anything
+ but the outermost type! */
+ if (!generating_instance_variables
+ && (obstack_object_size (&util_obstack) - curtype <= 1)
+ && (TYPE_NAME (type) && TREE_CODE (TYPE_NAME (type)) == TYPE_DECL
+ ? TYPE_READONLY (type)
+ : pointee_is_readonly (pointer_to)))
+ obstack_1grow (&util_obstack, 'r');
+ }
+
+ if (TREE_CODE (pointer_to) == RECORD_TYPE)
+ {
+ if (OBJC_TYPE_NAME (pointer_to)
+ && TREE_CODE (OBJC_TYPE_NAME (pointer_to)) == IDENTIFIER_NODE)
+ {
+ const char *name = IDENTIFIER_POINTER (OBJC_TYPE_NAME (pointer_to));
+
+ if (strcmp (name, TAG_OBJECT) == 0) /* '@' */
+ {
+ obstack_1grow (&util_obstack, '@');
+ return;
+ }
+ else if (TYPE_HAS_OBJC_INFO (pointer_to)
+ && TYPE_OBJC_INTERFACE (pointer_to))
+ {
+ if (generating_instance_variables)
+ {
+ obstack_1grow (&util_obstack, '@');
+ obstack_1grow (&util_obstack, '"');
+ obstack_grow (&util_obstack, name, strlen (name));
+ obstack_1grow (&util_obstack, '"');
+ return;
+ }
+ else
+ {
+ obstack_1grow (&util_obstack, '@');
+ return;
+ }
+ }
+ else if (strcmp (name, TAG_CLASS) == 0) /* '#' */
+ {
+ obstack_1grow (&util_obstack, '#');
+ return;
+ }
+ else if (strcmp (name, TAG_SELECTOR) == 0) /* ':' */
+ {
+ obstack_1grow (&util_obstack, ':');
+ return;
+ }
+ }
+ }
+ else if (TREE_CODE (pointer_to) == INTEGER_TYPE
+ && TYPE_MODE (pointer_to) == QImode)
+ {
+ tree pname = TREE_CODE (OBJC_TYPE_NAME (pointer_to)) == IDENTIFIER_NODE
+ ? OBJC_TYPE_NAME (pointer_to)
+ : DECL_NAME (OBJC_TYPE_NAME (pointer_to));
+
+ /* (BOOL *) are an exception and are encoded as ^c, while all
+ other pointers to char are encoded as *. */
+ if (strcmp (IDENTIFIER_POINTER (pname), "BOOL"))
+ {
+ if (!flag_next_runtime)
+ {
+ /* The NeXT runtime adds the 'r' before getting here. */
+
+ /* It appears that "r*" means "const char *" rather than
+ "char *const". "char *const" is encoded as "*",
+ which is identical to "char *", so the "const" is
+ unfortunately lost. */
+ if (TYPE_READONLY (pointer_to))
+ obstack_1grow (&util_obstack, 'r');
+ }
+
+ obstack_1grow (&util_obstack, '*');
+ return;
+ }
+ }
+
+ /* We have a normal pointer type that does not get special treatment. */
+ obstack_1grow (&util_obstack, '^');
+ encode_type (pointer_to, curtype, format);
+}
+
+static void
+encode_array (tree type, int curtype, int format)
+{
+ tree an_int_cst = TYPE_SIZE (type);
+ tree array_of = TREE_TYPE (type);
+ char buffer[40];
+
+ if (an_int_cst == NULL)
+ {
+ /* We are trying to encode an incomplete array. An incomplete
+ array is forbidden as part of an instance variable; but it
+ may occur if the instance variable is a pointer to such an
+ array. */
+
+ /* So the only case in which an incomplete array could occur
+ (without being pointed to) is if we are encoding the
+ arguments or return value of a method. In that case, an
+ incomplete array argument or return value (eg,
+ -(void)display: (char[])string) is treated like a pointer
+ because that is how the compiler does the function call. A
+ special, more complicated case, is when the incomplete array
+ is the last member of a struct (eg, if we are encoding
+ "struct { unsigned long int a;double b[];}"), which is again
+ part of a method argument/return value. In that case, we
+ really need to communicate to the runtime that there is an
+ incomplete array (not a pointer!) there. So, we detect that
+ special case and encode it as a zero-length array.
+
+ Try to detect that we are part of a struct. We do this by
+ searching for '=' in the type encoding for the current type.
+ NB: This hack assumes that you can't use '=' as part of a C
+ identifier.
+ */
+ {
+ char *enc = obstack_base (&util_obstack) + curtype;
+ if (memchr (enc, '=',
+ obstack_object_size (&util_obstack) - curtype) == NULL)
+ {
+ /* We are not inside a struct. Encode the array as a
+ pointer. */
+ encode_pointer (type, curtype, format);
+ return;
+ }
+ }
+
+ /* Else, we are in a struct, and we encode it as a zero-length
+ array. */
+ sprintf (buffer, "[" HOST_WIDE_INT_PRINT_DEC, (HOST_WIDE_INT)0);
+ }
+ else if (TREE_INT_CST_LOW (TYPE_SIZE (array_of)) == 0)
+ sprintf (buffer, "[" HOST_WIDE_INT_PRINT_DEC, (HOST_WIDE_INT)0);
+ else
+ sprintf (buffer, "[" HOST_WIDE_INT_PRINT_DEC,
+ TREE_INT_CST_LOW (an_int_cst)
+ / TREE_INT_CST_LOW (TYPE_SIZE (array_of)));
+
+ obstack_grow (&util_obstack, buffer, strlen (buffer));
+ encode_type (array_of, curtype, format);
+ obstack_1grow (&util_obstack, ']');
+ return;
+}
+
+/* Encode a vector. The vector type is a GCC extension to C. */
+static void
+encode_vector (tree type, int curtype, int format)
+{
+ tree vector_of = TREE_TYPE (type);
+ char buffer[40];
+
+ /* Vectors are like simple fixed-size arrays. */
+
+ /* Output ![xx,yy,<code>] where xx is the vector_size, yy is the
+ alignment of the vector, and <code> is the base type. Eg, int
+ __attribute__ ((vector_size (16))) gets encoded as ![16,32,i]
+ assuming that the alignment is 32 bytes. We include size and
+ alignment in bytes so that the runtime does not have to have any
+ knowledge of the actual types.
+ */
+ sprintf (buffer, "![" HOST_WIDE_INT_PRINT_DEC ",%d",
+ /* We want to compute the equivalent of sizeof (<vector>).
+ Code inspired by c_sizeof_or_alignof_type. */
+ ((TREE_INT_CST_LOW (TYPE_SIZE_UNIT (type))
+ / (TYPE_PRECISION (char_type_node) / BITS_PER_UNIT))),
+ /* We want to compute the equivalent of __alignof__
+ (<vector>). Code inspired by
+ c_sizeof_or_alignof_type. */
+ TYPE_ALIGN_UNIT (type));
+ obstack_grow (&util_obstack, buffer, strlen (buffer));
+ encode_type (vector_of, curtype, format);
+ obstack_1grow (&util_obstack, ']');
+ return;
+}
+
+static void
+encode_aggregate_fields (tree type, bool pointed_to, int curtype, int format)
+{
+ tree field = TYPE_FIELDS (type);
+
+ for (; field; field = DECL_CHAIN (field))
+ {
+#ifdef OBJCPLUS
+ /* C++ static members, and things that are not field at all,
+ should not appear in the encoding. */
+ if (TREE_CODE (field) != FIELD_DECL || TREE_STATIC (field))
+ continue;
+#endif
+
+ /* Recursively encode fields of embedded base classes. */
+ if (DECL_ARTIFICIAL (field) && !DECL_NAME (field)
+ && TREE_CODE (TREE_TYPE (field)) == RECORD_TYPE)
+ {
+ encode_aggregate_fields (TREE_TYPE (field),
+ pointed_to, curtype, format);
+ continue;
+ }
+
+ if (generating_instance_variables && !pointed_to)
+ {
+ tree fname = DECL_NAME (field);
+
+ obstack_1grow (&util_obstack, '"');
+
+ if (fname && TREE_CODE (fname) == IDENTIFIER_NODE)
+ obstack_grow (&util_obstack,
+ IDENTIFIER_POINTER (fname),
+ strlen (IDENTIFIER_POINTER (fname)));
+
+ obstack_1grow (&util_obstack, '"');
+ }
+
+ encode_field_decl (field, curtype, format);
+ }
+}
+
+static void
+encode_aggregate_within (tree type, int curtype, int format, int left,
+ int right)
+{
+ tree name;
+ /* NB: aggregates that are pointed to have slightly different encoding
+ rules in that you never encode the names of instance variables. */
+ int ob_size = obstack_object_size (&util_obstack);
+ bool inline_contents = false;
+ bool pointed_to = false;
+
+ if (flag_next_runtime)
+ {
+ if (ob_size > 0 && *(obstack_next_free (&util_obstack) - 1) == '^')
+ pointed_to = true;
+
+ if ((format == OBJC_ENCODE_INLINE_DEFS || generating_instance_variables)
+ && (!pointed_to || ob_size - curtype == 1
+ || (ob_size - curtype == 2
+ && *(obstack_next_free (&util_obstack) - 2) == 'r')))
+ inline_contents = true;
+ }
+ else
+ {
+ /* c0 and c1 are the last two characters in the encoding of the
+ current type; if the last two characters were '^' or '^r',
+ then we are encoding an aggregate that is "pointed to". The
+ comment above applies: in that case we should avoid encoding
+ the names of instance variables.
+ */
+ char c1 = ob_size > 1 ? *(obstack_next_free (&util_obstack) - 2) : 0;
+ char c0 = ob_size > 0 ? *(obstack_next_free (&util_obstack) - 1) : 0;
+
+ if (c0 == '^' || (c1 == '^' && c0 == 'r'))
+ pointed_to = true;
+
+ if (format == OBJC_ENCODE_INLINE_DEFS || generating_instance_variables)
+ {
+ if (!pointed_to)
+ inline_contents = true;
+ else
+ {
+ /* Note that the check (ob_size - curtype < 2) prevents
+ infinite recursion when encoding a structure which is
+ a linked list (eg, struct node { struct node *next;
+ }). Each time we follow a pointer, we add one
+ character to ob_size, and curtype is fixed, so after
+ at most two pointers we stop inlining contents and
+ break the loop.
+
+ The other case where we don't inline is "^r", which
+ is a pointer to a constant struct.
+ */
+ if ((ob_size - curtype <= 2) && !(c0 == 'r'))
+ inline_contents = true;
+ }
+ }
+ }
+
+ /* Traverse struct aliases; it is important to get the
+ original struct and its tag name (if any). */
+ type = TYPE_MAIN_VARIANT (type);
+ name = OBJC_TYPE_NAME (type);
+ /* Open parenth/bracket. */
+ obstack_1grow (&util_obstack, left);
+
+ /* Encode the struct/union tag name, or '?' if a tag was
+ not provided. Typedef aliases do not qualify. */
+#ifdef OBJCPLUS
+ /* For compatibility with the NeXT runtime, ObjC++ encodes template
+ args as a composite struct tag name. */
+ if (name && TREE_CODE (name) == IDENTIFIER_NODE
+ /* Did this struct have a tag? */
+ && !TYPE_WAS_ANONYMOUS (type))
+ obstack_grow (&util_obstack,
+ decl_as_string (type, TFF_DECL_SPECIFIERS | TFF_UNQUALIFIED_NAME),
+ strlen (decl_as_string (type, TFF_DECL_SPECIFIERS | TFF_UNQUALIFIED_NAME)));
+#else
+ if (name && TREE_CODE (name) == IDENTIFIER_NODE)
+ obstack_grow (&util_obstack,
+ IDENTIFIER_POINTER (name),
+ strlen (IDENTIFIER_POINTER (name)));
+#endif
+ else
+ obstack_1grow (&util_obstack, '?');
+
+ /* Encode the types (and possibly names) of the inner fields,
+ if required. */
+ if (inline_contents)
+ {
+ obstack_1grow (&util_obstack, '=');
+ encode_aggregate_fields (type, pointed_to, curtype, format);
+ }
+ /* Close parenth/bracket. */
+ obstack_1grow (&util_obstack, right);
+}
+
+/* Encode a bitfield NeXT-style (i.e., without a bit offset or the underlying
+ field type. */
+static void
+encode_next_bitfield (int width)
+{
+ char buffer[40];
+ sprintf (buffer, "b%d", width);
+ obstack_grow (&util_obstack, buffer, strlen (buffer));
+}
+
+/* Encodes 'type', ignoring type qualifiers (which you should encode
+ beforehand if needed) with the exception of 'const', which is
+ encoded by encode_type. See above for the explanation of
+ 'curtype'. 'format' can be OBJC_ENCODE_INLINE_DEFS or
+ OBJC_ENCODE_DONT_INLINE_DEFS. */
+static void
+encode_type (tree type, int curtype, int format)
+{
+ enum tree_code code = TREE_CODE (type);
+
+ /* Ignore type qualifiers other than 'const' when encoding a
+ type. */
+
+ if (type == error_mark_node)
+ return;
+
+ if (!flag_next_runtime)
+ {
+ if (TYPE_READONLY (type))
+ obstack_1grow (&util_obstack, 'r');
+ }
+
+ switch (code)
+ {
+ case ENUMERAL_TYPE:
+ if (flag_next_runtime)
+ {
+ /* Kludge for backwards-compatibility with gcc-3.3: enums
+ are always encoded as 'i' no matter what type they
+ actually are (!). */
+ obstack_1grow (&util_obstack, 'i');
+ break;
+ }
+ /* Else, they are encoded exactly like the integer type that is
+ used by the compiler to store them. */
+ case INTEGER_TYPE:
+ {
+ char c;
+ switch (GET_MODE_BITSIZE (TYPE_MODE (type)))
+ {
+ case 8: c = TYPE_UNSIGNED (type) ? 'C' : 'c'; break;
+ case 16: c = TYPE_UNSIGNED (type) ? 'S' : 's'; break;
+ case 32:
+ {
+ tree int_type = type;
+ if (flag_next_runtime)
+ {
+ /* Another legacy kludge for compatiblity with
+ gcc-3.3: 32-bit longs are encoded as 'l' or 'L',
+ but not always. For typedefs, we need to use 'i'
+ or 'I' instead if encoding a struct field, or a
+ pointer! */
+ int_type = ((!generating_instance_variables
+ && (obstack_object_size (&util_obstack)
+ == (unsigned) curtype))
+ ? TYPE_MAIN_VARIANT (type)
+ : type);
+ }
+ if (int_type == long_unsigned_type_node
+ || int_type == long_integer_type_node)
+ c = TYPE_UNSIGNED (type) ? 'L' : 'l';
+ else
+ c = TYPE_UNSIGNED (type) ? 'I' : 'i';
+ }
+ break;
+ case 64: c = TYPE_UNSIGNED (type) ? 'Q' : 'q'; break;
+ case 128: c = TYPE_UNSIGNED (type) ? 'T' : 't'; break;
+ default: gcc_unreachable ();
+ }
+ obstack_1grow (&util_obstack, c);
+ break;
+ }
+ case REAL_TYPE:
+ {
+ char c;
+ /* Floating point types. */
+ switch (GET_MODE_BITSIZE (TYPE_MODE (type)))
+ {
+ case 32: c = 'f'; break;
+ case 64: c = 'd'; break;
+ case 96:
+ case 128: c = 'D'; break;
+ default: gcc_unreachable ();
+ }
+ obstack_1grow (&util_obstack, c);
+ break;
+ }
+ case VOID_TYPE:
+ obstack_1grow (&util_obstack, 'v');
+ break;
+
+ case BOOLEAN_TYPE:
+ obstack_1grow (&util_obstack, 'B');
+ break;
+
+ case ARRAY_TYPE:
+ encode_array (type, curtype, format);
+ break;
+
+ case POINTER_TYPE:
+#ifdef OBJCPLUS
+ case REFERENCE_TYPE:
+#endif
+ encode_pointer (type, curtype, format);
+ break;
+
+ case RECORD_TYPE:
+ encode_aggregate_within (type, curtype, format, '{', '}');
+ break;
+
+ case UNION_TYPE:
+ encode_aggregate_within (type, curtype, format, '(', ')');
+ break;
+
+ case FUNCTION_TYPE: /* '?' means an unknown type. */
+ obstack_1grow (&util_obstack, '?');
+ break;
+
+ case COMPLEX_TYPE:
+ /* A complex is encoded as 'j' followed by the inner type (eg,
+ "_Complex int" is encoded as 'ji'). */
+ obstack_1grow (&util_obstack, 'j');
+ encode_type (TREE_TYPE (type), curtype, format);
+ break;
+
+ case VECTOR_TYPE:
+ encode_vector (type, curtype, format);
+ break;
+
+ default:
+ warning (0, "unknown type %<%T%> found during Objective-C encoding",
+ TREE_TYPE (type));
+ obstack_1grow (&util_obstack, '?');
+ break;
+ }
+
+ if (flag_next_runtime)
+ {
+ /* Super-kludge. Some ObjC qualifier and type combinations need
+ to be rearranged for compatibility with gcc-3.3. */
+ if (code == POINTER_TYPE && obstack_object_size (&util_obstack) >= 3)
+ {
+ char *enc = obstack_base (&util_obstack) + curtype;
+
+ /* Rewrite "in const" from "nr" to "rn". */
+ if (curtype >= 1 && !strncmp (enc - 1, "nr", 2))
+ strncpy (enc - 1, "rn", 2);
+ }
+ }
+}
+
+static void
+encode_gnu_bitfield (int position, tree type, int size)
+{
+ enum tree_code code = TREE_CODE (type);
+ char buffer[40];
+ char charType = '?';
+
+ /* This code is only executed for the GNU runtime, so we can ignore
+ the NeXT runtime kludge of always encoding enums as 'i' no matter
+ what integers they actually are. */
+ if (code == INTEGER_TYPE || code == ENUMERAL_TYPE)
+ {
+ if (integer_zerop (TYPE_MIN_VALUE (type)))
+ /* Unsigned integer types. */
+ {
+ switch (TYPE_MODE (type))
+ {
+ case QImode:
+ charType = 'C'; break;
+ case HImode:
+ charType = 'S'; break;
+ case SImode:
+ {
+ if (type == long_unsigned_type_node)
+ charType = 'L';
+ else
+ charType = 'I';
+ break;
+ }
+ case DImode:
+ charType = 'Q'; break;
+ default:
+ gcc_unreachable ();
+ }
+ }
+ else
+ /* Signed integer types. */
+ {
+ switch (TYPE_MODE (type))
+ {
+ case QImode:
+ charType = 'c'; break;
+ case HImode:
+ charType = 's'; break;
+ case SImode:
+ {
+ if (type == long_integer_type_node)
+ charType = 'l';
+ else
+ charType = 'i';
+ break;
+ }
+ case DImode:
+ charType = 'q'; break;
+ default:
+ gcc_unreachable ();
+ }
+ }
+ }
+ else
+ {
+ /* Do not do any encoding, produce an error and keep going. */
+ error ("trying to encode non-integer type as a bitfield");
+ return;
+ }
+
+ sprintf (buffer, "b%d%c%d", position, charType, size);
+ obstack_grow (&util_obstack, buffer, strlen (buffer));
+}
+
+void
+encode_field_decl (tree field_decl, int curtype, int format)
+{
+#ifdef OBJCPLUS
+ /* C++ static members, and things that are not fields at all,
+ should not appear in the encoding. */
+ if (TREE_CODE (field_decl) != FIELD_DECL || TREE_STATIC (field_decl))
+ return;
+#endif
+
+ /* Generate the bitfield typing information, if needed. Note the difference
+ between GNU and NeXT runtimes. */
+ if (DECL_BIT_FIELD_TYPE (field_decl))
+ {
+ int size = tree_low_cst (DECL_SIZE (field_decl), 1);
+
+ if (flag_next_runtime)
+ encode_next_bitfield (size);
+ else
+ encode_gnu_bitfield (int_bit_position (field_decl),
+ DECL_BIT_FIELD_TYPE (field_decl), size);
+ }
+ else
+ encode_type (TREE_TYPE (field_decl), curtype, format);
+}
+
+/* This routine encodes the attribute of the input PROPERTY according
+ to following formula:
+
+ Property attributes are stored as a comma-delimited C string.
+ Simple attributes such as readonly are encoded as single
+ character. The parametrized attributes, getter=name and
+ setter=name, are encoded as a single character followed by an
+ identifier. Property types are also encoded as a parametrized
+ attribute. The characters used to encode these attributes are
+ defined by the following enumeration:
+
+ enum PropertyAttributes {
+ kPropertyReadOnly = 'R',
+ kPropertyBycopy = 'C',
+ kPropertyByref = '&',
+ kPropertyDynamic = 'D',
+ kPropertyGetter = 'G',
+ kPropertySetter = 'S',
+ kPropertyInstanceVariable = 'V',
+ kPropertyType = 'T',
+ kPropertyWeak = 'W',
+ kPropertyStrong = 'P',
+ kPropertyNonAtomic = 'N'
+ }; */
+tree
+objc_v2_encode_prop_attr (tree property)
+{
+ const char *string;
+ tree type = TREE_TYPE (property);
+
+ obstack_1grow (&util_obstack, 'T');
+ encode_type (type, obstack_object_size (&util_obstack),
+ OBJC_ENCODE_INLINE_DEFS);
+
+ if (PROPERTY_READONLY (property))
+ obstack_grow (&util_obstack, ",R", 2);
+
+ switch (PROPERTY_ASSIGN_SEMANTICS (property))
+ {
+ case OBJC_PROPERTY_COPY:
+ obstack_grow (&util_obstack, ",C", 2);
+ break;
+ case OBJC_PROPERTY_RETAIN:
+ obstack_grow (&util_obstack, ",&", 2);
+ break;
+ case OBJC_PROPERTY_ASSIGN:
+ default:
+ break;
+ }
+
+ if (PROPERTY_DYNAMIC (property))
+ obstack_grow (&util_obstack, ",D", 2);
+
+ if (PROPERTY_NONATOMIC (property))
+ obstack_grow (&util_obstack, ",N", 2);
+
+ /* Here we want to encode the getter name, but only if it's not the
+ standard one. */
+ if (PROPERTY_GETTER_NAME (property) != PROPERTY_NAME (property))
+ {
+ obstack_grow (&util_obstack, ",G", 2);
+ string = IDENTIFIER_POINTER (PROPERTY_GETTER_NAME (property));
+ obstack_grow (&util_obstack, string, strlen (string));
+ }
+
+ if (!PROPERTY_READONLY (property))
+ {
+ /* Here we want to encode the setter name, but only if it's not
+ the standard one. */
+ tree standard_setter = get_identifier (objc_build_property_setter_name (PROPERTY_NAME (property)));
+ if (PROPERTY_SETTER_NAME (property) != standard_setter)
+ {
+ obstack_grow (&util_obstack, ",S", 2);
+ string = IDENTIFIER_POINTER (PROPERTY_SETTER_NAME (property));
+ obstack_grow (&util_obstack, string, strlen (string));
+ }
+ }
+
+ /* TODO: Encode strong ('P'), weak ('W') for garbage collection. */
+
+ if (!PROPERTY_DYNAMIC (property))
+ {
+ obstack_grow (&util_obstack, ",V", 2);
+ if (PROPERTY_IVAR_NAME (property))
+ string = IDENTIFIER_POINTER (PROPERTY_IVAR_NAME (property));
+ else
+ string = IDENTIFIER_POINTER (PROPERTY_NAME (property));
+ obstack_grow (&util_obstack, string, strlen (string));
+ }
+
+ /* NULL-terminate string. */
+ obstack_1grow (&util_obstack, 0);
+ string = XOBFINISH (&util_obstack, char *);
+ obstack_free (&util_obstack, util_firstobj);
+ return get_identifier (string);
+}
diff --git a/gcc/objc/objc-encoding.h b/gcc/objc/objc-encoding.h
new file mode 100644
index 00000000000..2fad5937bc9
--- /dev/null
+++ b/gcc/objc/objc-encoding.h
@@ -0,0 +1,74 @@
+/* Routines dealing with ObjC encoding of types
+ Copyright (C) 1992, 1993, 1994, 1995, 1997, 1998, 1999, 2000, 2001,
+ 2002, 2003, 2004, 2005, 2007, 2008, 2009, 2010, 2011
+ Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 3, or (at your option)
+any later version.
+
+GCC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3. If not see
+<http://www.gnu.org/licenses/>. */
+
+#ifndef GCC_OBJC_ENCODING_H
+#define GCC_OBJC_ENCODING_H
+
+/* TODO: Hide the following obstack code in objc-encoding.c, and have
+ a objc_encoding_init() that is called by objc_init() to set them
+ up. */
+
+/* Set up for use of obstacks. */
+#include "obstack.h"
+
+/* This obstack is used to accumulate the encoding of a data type. */
+extern struct obstack util_obstack;
+
+/* This points to the beginning of obstack contents, so we can free
+ the whole contents. */
+extern char *util_firstobj;
+
+/* This will be used to initialize the obstacks used by encoding. It
+ should be called before any encoding function is used. It is
+ usually done in objc_init(). */
+/* extern void objc_encoding_init (void); */
+
+
+/* Encode a method prototype. The format is described in
+ gcc/doc/objc.texi, section 'Method signatures'. */
+extern tree encode_method_prototype (tree method_decl);
+
+/* This is used to implement @encode(). See gcc/doc/objc.texi,
+ section '@encode'. */
+extern tree objc_build_encode_expr (tree type);
+
+/* (Decide if these can ever be validly changed.) */
+#define OBJC_ENCODE_INLINE_DEFS 0
+#define OBJC_ENCODE_DONT_INLINE_DEFS 1
+
+/* Encode the attributes of a property. */
+extern tree objc_v2_encode_prop_attr (tree property);
+
+/* Encode the type of a field. */
+extern void encode_field_decl (tree field_decl, int curtype, int format);
+
+/* Tells "encode_pointer/encode_aggregate" whether we are generating
+ type descriptors for instance variables (as opposed to methods).
+ Type descriptors for instance variables contain more information
+ than methods (for static typing and embedded structures).
+
+ TODO: Replace this global variable with an argument that is passed
+ to the various encode() functions.
+
+ TODO: Change it to a 'bool'. */
+extern int generating_instance_variables;
+
+#endif /* GCC_OBJC_ENCODING_H */
diff --git a/gcc/objc/objc-gnu-runtime-abi-01.c b/gcc/objc/objc-gnu-runtime-abi-01.c
index d21f2e9a6b5..fef5355c6a6 100644
--- a/gcc/objc/objc-gnu-runtime-abi-01.c
+++ b/gcc/objc/objc-gnu-runtime-abi-01.c
@@ -47,6 +47,7 @@ along with GCC; see the file COPYING3. If not see
#include "objc-runtime-hooks.h"
#include "objc-runtime-shared-support.h"
+#include "objc-encoding.h"
/* GNU runtime private definitions. */
#define DEF_CONSTANT_STRING_CLASS_NAME "NXConstantString"
diff --git a/gcc/objc/objc-next-runtime-abi-01.c b/gcc/objc/objc-next-runtime-abi-01.c
index d5b795fbb0e..6183a21e5e8 100644
--- a/gcc/objc/objc-next-runtime-abi-01.c
+++ b/gcc/objc/objc-next-runtime-abi-01.c
@@ -54,6 +54,7 @@ along with GCC; see the file COPYING3. If not see
#include "objc-runtime-hooks.h"
#include "objc-runtime-shared-support.h"
+#include "objc-encoding.h"
/* NeXT ABI 0 and 1 private definitions. */
#define DEF_CONSTANT_STRING_CLASS_NAME "NSConstantString"
diff --git a/gcc/objc/objc-next-runtime-abi-02.c b/gcc/objc/objc-next-runtime-abi-02.c
index fd9bb9923de..e7570c7e4b2 100644
--- a/gcc/objc/objc-next-runtime-abi-02.c
+++ b/gcc/objc/objc-next-runtime-abi-02.c
@@ -58,8 +58,8 @@ extern struct obstack util_obstack;
extern char *util_firstobj;
#include "objc-runtime-hooks.h"
-
#include "objc-runtime-shared-support.h"
+#include "objc-encoding.h"
/* ABI 2 Private definitions. */
#define DEF_CONSTANT_STRING_CLASS_NAME "NSConstantString"
diff --git a/gcc/objc/objc-runtime-shared-support.c b/gcc/objc/objc-runtime-shared-support.c
index 78505f4d5e8..913b0fd7e2b 100644
--- a/gcc/objc/objc-runtime-shared-support.c
+++ b/gcc/objc/objc-runtime-shared-support.c
@@ -51,6 +51,7 @@ extern char *util_firstobj;
#include "objc-runtime-hooks.h"
#include "objc-runtime-shared-support.h"
+#include "objc-encoding.h"
/* rt_trees identifiers - shared between NeXT implementations. These allow
the FE to tag meta-data in a manner that survives LTO and can be used when
diff --git a/gcc/objc/objc-runtime-shared-support.h b/gcc/objc/objc-runtime-shared-support.h
index bb0e5711df0..0db8bed1240 100644
--- a/gcc/objc/objc-runtime-shared-support.h
+++ b/gcc/objc/objc-runtime-shared-support.h
@@ -52,20 +52,17 @@ extern void objc_push_parm (tree);
extern tree build_function_type_for_method (tree, tree, int, bool);
+extern char *objc_build_property_setter_name (tree);
+
/* Stuff that should be migrated to shared support (or some v1-only file). */
extern void build_super_template (void);
extern tree objc_build_component_ref (tree, tree);
-extern tree objc_v2_encode_prop_attr (tree);
extern tree build_descriptor_table_initializer (tree, tree);
extern tree build_method_prototype_list_template (tree, int);
extern tree build_protocol_initializer (tree, tree, tree, tree, tree);
-/* Stuff that should be migrated to shared encode. */
-extern tree encode_method_prototype (tree);
-extern void encode_field_decl (tree, int, int);
-
/* Moved or new routines in objc-runtime-shared-support.c */
extern tree build_selector (tree);
@@ -85,7 +82,6 @@ extern tree build_ivar_template (void);
extern void generate_strings (void);
extern void dump_interface (FILE *, tree);
-extern int generating_instance_variables;
extern FILE *gen_declaration_file;
#endif /* _OBJC_RUNTIME_SHARED_SUPPORT_H_ */