From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from pv34p98im-ztdg02172101.me.com (pv34p98im-ztdg02172101.me.com [17.143.234.142]) by sourceware.org (Postfix) with ESMTPS id DC980385840E for ; Mon, 27 Sep 2021 03:45:14 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org DC980385840E Received: from [10.0.1.20] (cpe-98-26-0-177.nc.res.rr.com [98.26.0.177]) by pv34p98im-ztdg02172101.me.com (Postfix) with ESMTPSA id 33621540017 for ; Mon, 27 Sep 2021 03:45:13 +0000 (UTC) From: Matt Jacobson Content-Type: text/plain; charset=us-ascii Content-Transfer-Encoding: quoted-printable Mime-Version: 1.0 (Mac OS X Mail 13.4 \(3608.120.23.2.7\)) Subject: [PATCH] Objective-C: fix protocol list count type (pertinent to non-LP64) Message-Id: <3FA161CB-9D8F-4576-8607-292CE21B2BF3@me.com> Date: Sun, 26 Sep 2021 23:45:10 -0400 To: gcc-patches@gcc.gnu.org X-Mailer: Apple Mail (2.3608.120.23.2.7) X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10434:6.0.391, 18.0.790 definitions=2021-09-27_01:2021-09-24, 2021-09-27 signatures=0 X-Proofpoint-Spam-Details: rule=notspam policy=default score=0 suspectscore=0 malwarescore=0 phishscore=0 bulkscore=0 spamscore=0 clxscore=1015 mlxscore=0 mlxlogscore=999 adultscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.0.1-2009150000 definitions=main-2109270024 X-Spam-Status: No, score=-12.5 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, FREEMAIL_FROM, GIT_PATCH_0, RCVD_IN_DNSWL_LOW, SPF_HELO_NONE, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.4 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on server2.sourceware.org X-BeenThere: gcc-patches@gcc.gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gcc-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 27 Sep 2021 03:45:17 -0000 Fix protocol list layout for non-LP64. clang and objc4 both give the = `count`=20 field as `long`, not `intptr_t`. Those are the same on LP64, but not=20 everywhere. For non-LP64, this fixes binary compatibility with = clang-built=20 classes. This was more complicated than I anticipated, because the relevant = frontend=20 code in fact had no AST type for `protocol_list_t`, instead emitting = protocol=20 lists as `protocol_t[]`, with the zeroth element actually being the = integer=20 count. That made it nontrivial to change the count to `long`. With = this=20 change, there is now a true `protocol_list_t` type in the AST. Tested multiple ways. On x86_64/Darwin, I confirmed with a test program = that=20 protocol conformances by classes, categories, and protocols works. On = AVR, I=20 manually inspected the generated assembly to confirm that protocol lists = gain=20 an extra two bytes of `count`, matching clang. Thank you for your time. = gcc/objc/ChangeLog: 2021-09-26 Matt Jacobson * objc-next-runtime-abi-02.c (enum objc_v2_tree_index): Add new = global tree. (static void next_runtime_02_initialize): Initialize protocol = list type tree. (struct class_ro_t): Fix type misspelling. (build_v2_class_templates): Correct type in field declaration. (build_v2_protocol_templates): Create actual protocol list type = tree. (build_v2_category_template): Correct type in field declaration. (generate_v2_protocol_list): Emit protocol list count as `long`. (generate_v2_protocols): Use correct type. (build_v2_category_initializer): Use correct type. (build_v2_class_ro_t_initializer): Use correct type. diff --git a/gcc/objc/objc-next-runtime-abi-02.c = b/gcc/objc/objc-next-runtime-abi-02.c index c3af369ff0d..aadf1741676 100644 --- a/gcc/objc/objc-next-runtime-abi-02.c +++ b/gcc/objc/objc-next-runtime-abi-02.c @@ -92,6 +92,7 @@ enum objc_v2_tree_index OCTI_V2_CAT_TEMPL, OCTI_V2_CLS_RO_TEMPL, OCTI_V2_PROTO_TEMPL, + OCTI_V2_PROTO_LIST_TEMPL, OCTI_V2_IVAR_TEMPL, OCTI_V2_IVAR_LIST_TEMPL, OCTI_V2_MESSAGE_REF_TEMPL, @@ -130,6 +131,8 @@ enum objc_v2_tree_index objc_v2_global_trees[OCTI_V2_CAT_TEMPL] #define objc_v2_protocol_template \ = objc_v2_global_trees[OCTI_V2_PROTO_TEMPL] +#define objc_v2_protocol_list_template \ + = objc_v2_global_trees[OCTI_V2_PROTO_LIST_TEMPL] =20 /* struct message_ref_t */ #define objc_v2_message_ref_template \ @@ -196,7 +199,7 @@ static void build_v2_message_ref_templates (void); static void build_v2_class_templates (void); static void build_v2_super_template (void); static void build_v2_category_template (void); -static void build_v2_protocol_template (void); +static void build_v2_protocol_templates (void); =20 static tree next_runtime_abi_02_super_superclassfield_id (void); =20 @@ -394,9 +397,9 @@ static void next_runtime_02_initialize (void) build_pointer_type (xref_tag (RECORD_TYPE, get_identifier ("_prop_list_t"))); =20 + build_v2_protocol_templates (); build_v2_class_templates (); build_v2_super_template (); - build_v2_protocol_template (); build_v2_category_template (); =20 bool fixup_p =3D flag_next_runtime < USE_FIXUP_BEFORE; @@ -636,7 +639,7 @@ struct class_ro_t const uint8_t * const ivarLayout; const char *const name; const struct method_list_t * const baseMethods; - const struct objc_protocol_list *const baseProtocols; + const struct protocol_list_t *const baseProtocols; const struct ivar_list_t *const ivars; const uint8_t * const weakIvarLayout; const struct _prop_list_t * const properties; @@ -685,11 +688,9 @@ build_v2_class_templates (void) /* const struct method_list_t * const baseMethods; */ add_field_decl (objc_method_list_ptr, "baseMethods", &chain); =20 - /* const struct objc_protocol_list *const baseProtocols; */ - add_field_decl (build_pointer_type - (xref_tag (RECORD_TYPE, - get_identifier = (UTAG_V2_PROTOCOL_LIST))), - "baseProtocols", &chain); + /* const struct protocol_list_t *const baseProtocols; */ + add_field_decl (build_pointer_type (objc_v2_protocol_list_template), + "baseProtocols", &chain); =20 /* const struct ivar_list_t *const ivars; */ add_field_decl (objc_v2_ivar_list_ptr, "ivars", &chain); @@ -763,25 +764,33 @@ build_v2_super_template (void) const char ** extended_method_types; const char * demangled_name; const struct _prop_list_t * class_properties; - } + }; + + struct protocol_list_t + { + long count; + struct protocol_t protocols[]; + }; */ static void -build_v2_protocol_template (void) +build_v2_protocol_templates (void) { - tree decls, *chain =3D NULL; + tree decls, protolist_pointer_type, protocol_pointer_type, *chain; =20 objc_v2_protocol_template =3D objc_start_struct (get_identifier (UTAG_V2_PROTOCOL)); =20 /* Class isa; */ + chain =3D NULL; decls =3D add_field_decl (objc_object_type, "isa", &chain); =20 /* char *protocol_name; */ add_field_decl (string_type_node, "protocol_name", &chain); =20 /* const struct protocol_list_t * const protocol_list; */ - add_field_decl (build_pointer_type (objc_v2_protocol_template), - "protocol_list", &chain); + protolist_pointer_type =3D build_pointer_type (xref_tag (RECORD_TYPE, + get_identifier = (UTAG_V2_PROTOCOL_LIST))); + add_field_decl (protolist_pointer_type, "protocol_list", &chain); =20 /* const struct method_list_t * const instance_methods; */ add_field_decl (objc_method_proto_list_ptr, "instance_methods", = &chain); @@ -815,6 +824,24 @@ build_v2_protocol_template (void) add_field_decl (objc_prop_list_ptr, "class_properties", &chain); =20 objc_finish_struct (objc_v2_protocol_template, decls); + + /* --- */ + + objc_v2_protocol_list_template =3D + objc_start_struct (get_identifier = (UTAG_V2_PROTOCOL_LIST)); + gcc_assert (TREE_TYPE (protolist_pointer_type) + =3D=3D objc_v2_protocol_list_template); + + /* long count; */ + chain =3D NULL; + decls =3D add_field_decl (long_integer_type_node, "count", &chain); + + /* struct protocol_t *protocols[]; */ + protocol_pointer_type =3D build_pointer_type = (objc_v2_protocol_template); + add_field_decl (build_array_type (protocol_pointer_type, 0), = "protocols", + &chain); + + objc_finish_struct (objc_v2_protocol_list_template, decls); } =20 /* Build type for a category: @@ -850,7 +877,7 @@ build_v2_category_template (void) add_field_decl (objc_method_list_ptr, "class_methods", &chain); =20 /* struct protocol_list_t *protocol_list; */ - add_field_decl (build_pointer_type (objc_v2_protocol_template), + add_field_decl (build_pointer_type (objc_v2_protocol_list_template), "protocol_list", &chain ); =20 /* struct _prop_list_t * properties; */ @@ -2323,9 +2350,9 @@ build_v2_protocol_list_address_table (void) static tree generate_v2_protocol_list (tree i_or_p, tree klass_ctxt) { - tree refs_decl, lproto, e, plist, ptempl_p_t; + tree refs_decl, lproto, plist, protocol_pointer_type, array_ctor, = ctor; int size =3D 0; - vec *initlist =3D NULL; + vec *initlist =3D NULL, *subinitlist =3D = NULL; char buf[BUFSIZE]; =20 if (TREE_CODE (i_or_p) =3D=3D CLASS_INTERFACE_TYPE @@ -2336,18 +2363,7 @@ generate_v2_protocol_list (tree i_or_p, tree = klass_ctxt) else gcc_unreachable (); =20 - /* Compute size. */ - for (lproto =3D plist; lproto; lproto =3D TREE_CHAIN (lproto)) - if (TREE_CODE (TREE_VALUE (lproto)) =3D=3D PROTOCOL_INTERFACE_TYPE - && PROTOCOL_FORWARD_DECL (TREE_VALUE (lproto))) - size++; - - /* Build initializer. */ - - ptempl_p_t =3D build_pointer_type (objc_v2_protocol_template); - e =3D build_int_cst (ptempl_p_t, size); - CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, e); - + /* Compute size, and build array initializer. */ for (lproto =3D plist; lproto; lproto =3D TREE_CHAIN (lproto)) { tree pval =3D TREE_VALUE (lproto); @@ -2356,14 +2372,24 @@ generate_v2_protocol_list (tree i_or_p, tree = klass_ctxt) && PROTOCOL_FORWARD_DECL (pval)) { tree fwref =3D PROTOCOL_FORWARD_DECL (pval); - location_t loc =3D DECL_SOURCE_LOCATION (fwref) ; - e =3D build_unary_op (loc, ADDR_EXPR, fwref, 0); - CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, e); + location_t loc =3D DECL_SOURCE_LOCATION (fwref); + tree e =3D build_unary_op (loc, ADDR_EXPR, fwref, 0); + CONSTRUCTOR_APPEND_ELT (subinitlist, + build_int_cst (NULL_TREE, size), e); + + size++; } } =20 - /* static struct protocol_list_t *list[size]; */ + /* Build struct initializer. */ + CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, + build_int_cst (long_integer_type_node, size)); + protocol_pointer_type =3D build_pointer_type = (objc_v2_protocol_template); + array_ctor =3D objc_build_constructor ( + build_array_type (protocol_pointer_type, 0), = subinitlist); + CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, array_ctor); =20 + /* Build declaration name. */ switch (TREE_CODE (i_or_p)) { case PROTOCOL_INTERFACE_TYPE: @@ -2383,13 +2409,13 @@ generate_v2_protocol_list (tree i_or_p, tree = klass_ctxt) gcc_unreachable (); } =20 - refs_decl =3D start_var_decl (build_sized_array_type (ptempl_p_t, = size+1), - buf); + /* Build declaration. */ + refs_decl =3D start_var_decl (objc_v2_protocol_list_template, buf); /* ObjC2 puts all these in the base section. */ OBJCMETA (refs_decl, objc_meta, meta_base); DECL_PRESERVE_P (refs_decl) =3D 1; - finish_var_decl (refs_decl, - objc_build_constructor (TREE_TYPE = (refs_decl),initlist)); + ctor =3D objc_build_constructor (objc_v2_protocol_list_template, = initlist); + finish_var_decl (refs_decl, ctor); return refs_decl; } =20 @@ -2794,8 +2820,9 @@ generate_v2_protocols (void) protocol_name_expr =3D add_objc_string (PROTOCOL_NAME (p), = class_names); =20 if (refs_decl) - refs_expr =3D convert (build_pointer_type = (objc_v2_protocol_template), - build_unary_op (loc, ADDR_EXPR, refs_decl, = 0)); + refs_expr =3D convert ( + build_pointer_type (objc_v2_protocol_list_template), + build_unary_op (loc, ADDR_EXPR, refs_decl, 0)); else refs_expr =3D build_int_cst (NULL_TREE, 0); =20 @@ -2885,8 +2912,7 @@ build_v2_category_initializer (tree type, tree = cat_name, tree class_name, expr =3D convert (ltyp, null_pointer_node); CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr); =20 - /* protocol_list =3D */ - ltyp =3D build_pointer_type (objc_v2_protocol_template); + ltyp =3D build_pointer_type (objc_v2_protocol_list_template); if (protocol_list) expr =3D convert (ltyp, build_unary_op (loc, ADDR_EXPR, = protocol_list, 0)); else @@ -3238,8 +3264,7 @@ build_v2_class_ro_t_initializer (tree type, tree = name, CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, expr); =20 /* baseProtocols */ - ltyp =3D build_pointer_type (xref_tag (RECORD_TYPE, - get_identifier = (UTAG_V2_PROTOCOL_LIST))); + ltyp =3D build_pointer_type (objc_v2_protocol_list_template); if (baseProtocols) expr =3D convert (ltyp, build_unary_op (loc, ADDR_EXPR, = baseProtocols, 0)); else