From patchwork Sat Jul 2 18:06:30 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Nicola Pero X-Patchwork-Id: 102995 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) by ozlabs.org (Postfix) with SMTP id B19A2B6F57 for ; Sun, 3 Jul 2011 04:07:21 +1000 (EST) Received: (qmail 13666 invoked by alias); 2 Jul 2011 18:07:19 -0000 Received: (qmail 13640 invoked by uid 22791); 2 Jul 2011 18:07:10 -0000 X-SWARE-Spam-Status: No, hits=-0.0 required=5.0 tests=AWL, BAYES_50, TW_BJ, TW_CP, TW_JC, T_RP_MATCHES_RCVD X-Spam-Check-By: sourceware.org Received: from fencepost.gnu.org (HELO fencepost.gnu.org) (140.186.70.10) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Sat, 02 Jul 2011 18:06:46 +0000 Received: from eggs.gnu.org ([140.186.70.92]:34057) by fencepost.gnu.org with esmtps (TLS1.0:RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1Qd4ab-0002AF-4g for gcc-patches@gnu.org; Sat, 02 Jul 2011 14:06:45 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1Qd4aU-0006oW-42 for gcc-patches@gnu.org; Sat, 02 Jul 2011 14:06:44 -0400 Received: from smtp111.iad.emailsrvr.com ([207.97.245.111]:55042) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Qd4aT-0006ny-Kd for gcc-patches@gnu.org; Sat, 02 Jul 2011 14:06:37 -0400 Received: from localhost (localhost.localdomain [127.0.0.1]) by smtp51.relay.iad1a.emailsrvr.com (SMTP Server) with ESMTP id 7BEB02023C for ; Sat, 2 Jul 2011 14:06:35 -0400 (EDT) Received: by smtp51.relay.iad1a.emailsrvr.com (Authenticated sender: nicola.pero-AT-meta-innovation.com) with ESMTPSA id 127772019A for ; Sat, 2 Jul 2011 14:06:33 -0400 (EDT) From: Nicola Pero Subject: objc/objc++: refactor encoding code Date: Sat, 2 Jul 2011 19:06:30 +0100 Message-Id: <64794DD4-F8EF-4324-9CE4-5BE648CC8932@meta-innovation.com> To: gcc-patches@gnu.org Mime-Version: 1.0 (Apple Message framework v1084) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.6 (newer, 3) X-Received-From: 207.97.245.111 X-IsSubscribed: yes Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org This patch improves the modularity of the Objective-C Front-End by separating out the encoding code into separate objc-encoding.h and objc-encoding.c files. This patch only moves code around, without changing anything (with one exception, which is the replacement of gen_type_name() with the standard %T format string in a warning). There are a number of cleanups that would come naturally at this point, but I resisted temptation to implement them in this patch, reserving them for later patches so that we have a clear subversion history of changes. I did add a few TODO comments though. The performance impact of this patch should be minimal; there a few, well-defined entry points to the encoding machinery (such as calls to encode a method prototype, or an instance variable, or to produce an @encode string) and they were already standard functions; having them in one compilation unit or the other doesn't change anything. All the other encoding functions just call each other, and are static, so again moving them to a different unit has no performance impact. I reviewed the dependencies in the makefile while adding the new files. Ok to commit ? Thanks In gcc/objc/: 2011-07-02 Nicola Pero 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-02 Nicola Pero * 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. Index: objc/objc-encoding.c =================================================================== --- objc/objc-encoding.c (revision 0) +++ objc/objc-encoding.c (revision 0) @@ -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 +. */ + +#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,] where xx is the vector_size, yy is the + alignment of the vector, and 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 (). + 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__ + (). 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); +} Index: objc/objc-encoding.h =================================================================== --- objc/objc-encoding.h (revision 0) +++ objc/objc-encoding.h (revision 0) @@ -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 +. */ + +#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 */ Index: objc/ChangeLog =================================================================== --- objc/ChangeLog (revision 175590) +++ objc/ChangeLog (working copy) @@ -1,3 +1,47 @@ +2011-07-02 Nicola Pero + + 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 * objc-act.c (receiver_is_class_object): Expanded comment. Index: objc/objc-runtime-shared-support.c =================================================================== --- objc/objc-runtime-shared-support.c (revision 175590) +++ objc/objc-runtime-shared-support.c (working copy) @@ -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 Index: objc/Make-lang.in =================================================================== --- objc/Make-lang.in (revision 175590) +++ objc/Make-lang.in (working copy) @@ -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,34 +74,76 @@ cc1obj$(exeext): $(OBJC_OBJS) $(C_AND_OBJC_OBJS) c # 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 + 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 $(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-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 $(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-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 $(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-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 $(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) +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: # Index: objc/objc-runtime-shared-support.h =================================================================== --- objc/objc-runtime-shared-support.h (revision 175590) +++ objc/objc-runtime-shared-support.h (working copy) @@ -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_ */ Index: objc/objc-next-runtime-abi-01.c =================================================================== --- objc/objc-next-runtime-abi-01.c (revision 175590) +++ objc/objc-next-runtime-abi-01.c (working copy) @@ -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" Index: objc/objc-next-runtime-abi-02.c =================================================================== --- objc/objc-next-runtime-abi-02.c (revision 175590) +++ objc/objc-next-runtime-abi-02.c (working copy) @@ -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" Index: objc/objc-act.c =================================================================== --- objc/objc-act.c (revision 175590) +++ objc/objc-act.c (working copy) @@ -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))) 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 sel 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,759 +10162,7 @@ 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,] where xx is the vector_size, yy is the - alignment of the vector, and 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 (). - 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__ - (). 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) { c_common_init_ts (); Index: objc/objc-act.h =================================================================== --- objc/objc-act.h (revision 175590) +++ objc/objc-act.h (working copy) @@ -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 Index: objc/objc-gnu-runtime-abi-01.c =================================================================== --- objc/objc-gnu-runtime-abi-01.c (revision 175590) +++ objc/objc-gnu-runtime-abi-01.c (working copy) @@ -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" Index: objcp/Make-lang.in =================================================================== --- objcp/Make-lang.in (revision 175590) +++ objcp/Make-lang.in (working copy) @@ -57,6 +57,7 @@ OBJCXX_OBJS = objcp/objcp-act.o objcp/objcp-lang.o objcp/objc-gnu-runtime-abi-01.o \ objcp/objc-next-runtime-abi-01.o \ objcp/objc-next-runtime-abi-02.o \ + objcp/objc-encoding.o \ $(CXX_AND_OBJCXX_OBJS) obj-c++_OBJS = $(OBJCXX_OBJS) cc1objplus-checksum.o @@ -76,51 +77,99 @@ cc1objplus$(exeext): $(OBJCXX_OBJS) cc1objplus-che # Objective C++ language specific files. -objcp/objcp-lang.o : objcp/objcp-lang.c $(START_HDRS) \ +objcp/objcp-lang.o : objcp/objcp-lang.c \ + $(START_HDRS) \ + $(GGC_H) \ $(C_COMMON_H) $(LANGHOOKS_DEF_H) cp/cp-objcp-common.h \ $(TARGET_H) gtype-objcp.h objcp/objcp-decl.o : objcp/objcp-decl.c \ $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) $(CXX_TREE_H) \ - objc/objc-act.h objcp/objcp-decl.h c-family/c-objc.h + objc/objc-act.h c-family/c-objc.h \ + objcp/objcp-decl.h objcp/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 + 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 \ + objcp/objcp-decl.h $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $< \ $(OUTPUT_OPTION) -objcp/objc-gnu-runtime-abi-01.o: objc/objc-gnu-runtime-abi-01.c $(START_HDRS) \ - objc/objc-runtime-hooks.h $(GGC_H) \ - gt-objc-objc-gnu-runtime-abi-01.h toplev.h +objcp/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 \ + objcp/objcp-decl.h $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $< \ $(OUTPUT_OPTION) -objcp/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) +objcp/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 \ + objcp/objcp-decl.h $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $< \ $(OUTPUT_OPTION) -objcp/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) +objcp/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 \ + objcp/objcp-decl.h $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $< \ $(OUTPUT_OPTION) # The following must be an explicit rule; please keep in sync with the implicit # one in Makefile.in. -objcp/objcp-act.o : objc/objc-act.c $(START_HDRS) $(GGC_H) \ - $(RTL_H) $(EXPR_H) $(TARGET_H) $(DIAGNOSTIC_H) toplev.h $(FLAGS_H) \ - input.h $(FUNCTION_H) output.h debug.h $(OBSTACK_H) \ - objcp/objcp-decl.h $(LANGHOOKS_DEF_H) $(HASHTAB_H) gt-objc-objc-act.h \ - $(GIMPLE_H) objc/objc-runtime-hooks.h objc/objc-runtime-shared-support.h +objcp/objcp-act.o : objc/objc-act.c \ + gt-objc-objc-act.h \ + $(START_HDRS) \ + $(GGC_H) $(DIAGNOSTIC_H) $(FLAGS_H) input.h \ + $(OBSTACK_H) \ + toplev.h $(FUNCTION_H) output.h debug.h $(LANGHOOKS_DEF_H) \ + $(HASHTAB_H) $(GIMPLE_H) \ + $(RTL_H) $(EXPR_H) $(TARGET_H) \ + objcp/objcp-decl.h \ + objc/objc-encoding.h \ + objc/objc-runtime-hooks.h \ + objc/objc-runtime-shared-support.h \ + objcp/objcp-decl.h $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $< \ $(OUTPUT_OPTION) +objcp/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 \ + objcp/objcp-decl.h + $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $< \ + $(OUTPUT_OPTION) + po-generated: # Index: objcp/ChangeLog =================================================================== --- objcp/ChangeLog (revision 175590) +++ objcp/ChangeLog (working copy) @@ -1,3 +1,19 @@ +2011-07-02 Nicola Pero + + * 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. + 2011-04-15 Nicola Pero * objcp-decl.c (objcp_finish_struct): Use