From patchwork Wed Dec 15 14:50:27 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jakub Jelinek X-Patchwork-Id: 48941 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 03DB4385840B for ; Wed, 15 Dec 2021 14:51:07 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 03DB4385840B DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1639579867; bh=Y5YrMbEdrmDzVK7sfvwzlhfaTrAu1kdpUnwXLo296Io=; h=Date:To:Subject:References:In-Reply-To:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To:Cc: From; b=pRAgCm7/bKYrZiNBci67YvIHFd2aQjsL49RT6+J2xL4ArpLnAv7QSLJaag5XfimL9 KypCb05AYj1H2q3wE+vnLqMb8vgW6qmA7mxLvPzP079pP9yhuAc8QKCjBlelDPRSwz +DeJ6UJW3g9CY8SFRS2lODNU4UAPlFIGBARxSGj4= X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) by sourceware.org (Postfix) with ESMTPS id 923B13858D28 for ; Wed, 15 Dec 2021 14:50:37 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 923B13858D28 Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-21-gNDRUJMWN5SkMDoyLpwk8Q-1; Wed, 15 Dec 2021 09:50:34 -0500 X-MC-Unique: gNDRUJMWN5SkMDoyLpwk8Q-1 Received: from smtp.corp.redhat.com (int-mx04.intmail.prod.int.phx2.redhat.com [10.5.11.14]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id E50878015CD; Wed, 15 Dec 2021 14:50:31 +0000 (UTC) Received: from tucnak.zalov.cz (unknown [10.2.16.169]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 8174E17DBA; Wed, 15 Dec 2021 14:50:31 +0000 (UTC) Received: from tucnak.zalov.cz (localhost [127.0.0.1]) by tucnak.zalov.cz (8.16.1/8.16.1) with ESMTPS id 1BFEoSsa2509123 (version=TLSv1.3 cipher=TLS_AES_256_GCM_SHA384 bits=256 verify=NOT); Wed, 15 Dec 2021 15:50:29 +0100 Received: (from jakub@localhost) by tucnak.zalov.cz (8.16.1/8.16.1/Submit) id 1BFEoR752509122; Wed, 15 Dec 2021 15:50:27 +0100 Date: Wed, 15 Dec 2021 15:50:27 +0100 To: "H.J. Lu" , Jan Hubicka , Michael Matz , Uros Bizjak Subject: [PATCH] x86_64: Ignore zero width bitfields in ABI and issue -Wpsabi warning about C zero width bitfield ABI changes [PR102024] Message-ID: <20211215145027.GI2646553@tucnak> References: <20210831080558.GT920497@tucnak> <20211129102352.GD2646553@tucnak> MIME-Version: 1.0 In-Reply-To: X-Scanned-By: MIMEDefang 2.79 on 10.5.11.14 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Disposition: inline X-Spam-Status: No, score=-5.6 required=5.0 tests=BAYES_00, DKIMWL_WL_HIGH, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, KAM_SHORT, RCVD_IN_DNSWL_LOW, RCVD_IN_MSPIKE_H3, RCVD_IN_MSPIKE_WL, SPF_HELO_NONE, SPF_NONE, 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-Patchwork-Original-From: Jakub Jelinek via Gcc-patches From: Jakub Jelinek Reply-To: Jakub Jelinek Cc: Florian Weimer , GCC Patches Errors-To: gcc-patches-bounces+patchwork=sourceware.org@gcc.gnu.org Sender: "Gcc-patches" On Mon, Nov 29, 2021 at 05:25:30AM -0700, H.J. Lu wrote: > > I'd like to ping this patch, but perhaps first it would be nice to discuss > > it in the x86-64 psABI group. > > The current psABI doesn't seem to mention zero sized bitfields at all > > explicitly, so perhaps theoretically they should be treated as INTEGER class, > > but if they are at positions multiple of 64 bits, then it is unclear into > > which eightbyte they should be considered, whether the previous one if any > > or the next one if any. I guess similar problem is for zero sized > > structures, but those should according to algorithm have NO_CLASS and so it > > doesn't really make a difference. And, no compiler I'm aware of treats > > the zero sized bitfields at 64 bit boundaries as INTEGER class, LLVM/ICC are > > ignoring such bitfields everywhere, GCC ignores them at those boundaries > > (and used to ignore them in C++ everywhere). I guess my preferred solution > > would be to say explicitly that zero sized bitfields are NO_CLASS. > > I'm not a member of the google x86-64 psABI group, can somebody please raise > > it there? > > https://groups.google.com/g/x86-64-abi/c/OYeWs14WHQ4 Thanks. I see nobody commented on Micha's post there. Here is a patch that implements it in GCC, i.e. C++ doesn't change ABI (at least not from the past few releases) and C does for GCC: 2021-12-15 Jakub Jelinek PR target/102024 * config/i386/i386.c (classify_argument): Add zero_width_bitfields argument, when seeing DECL_FIELD_CXX_ZERO_WIDTH_BIT_FIELD bitfields, always ignore them, when seeing other zero sized bitfields, either set zero_width_bitfields to 1 and ignore it or if equal to 2 process it. Pass it to recursive calls. Add wrapper with old arguments and diagnose ABI differences for C structures with zero width bitfields. Formatting fixes. * gcc.target/i386/pr102024.c: New test. * g++.target/i386/pr102024.C: New test. Jakub --- gcc/config/i386/i386.c.jj 2021-12-10 17:00:06.024369219 +0100 +++ gcc/config/i386/i386.c 2021-12-15 15:04:49.245148023 +0100 @@ -2065,7 +2065,8 @@ merge_classes (enum x86_64_reg_class cla static int classify_argument (machine_mode mode, const_tree type, - enum x86_64_reg_class classes[MAX_CLASSES], int bit_offset) + enum x86_64_reg_class classes[MAX_CLASSES], int bit_offset, + int &zero_width_bitfields) { HOST_WIDE_INT bytes = mode == BLKmode ? int_size_in_bytes (type) : (int) GET_MODE_SIZE (mode); @@ -2123,6 +2124,16 @@ classify_argument (machine_mode mode, co misaligned integers. */ if (DECL_BIT_FIELD (field)) { + if (integer_zerop (DECL_SIZE (field))) + { + if (DECL_FIELD_CXX_ZERO_WIDTH_BIT_FIELD (field)) + continue; + if (zero_width_bitfields != 2) + { + zero_width_bitfields = 1; + continue; + } + } for (i = (int_bit_position (field) + (bit_offset % 64)) / 8 / 8; i < ((int_bit_position (field) + (bit_offset % 64)) @@ -2160,7 +2171,8 @@ classify_argument (machine_mode mode, co num = classify_argument (TYPE_MODE (type), type, subclasses, (int_bit_position (field) - + bit_offset) % 512); + + bit_offset) % 512, + zero_width_bitfields); if (!num) return 0; pos = (int_bit_position (field) @@ -2178,7 +2190,8 @@ classify_argument (machine_mode mode, co { int num; num = classify_argument (TYPE_MODE (TREE_TYPE (type)), - TREE_TYPE (type), subclasses, bit_offset); + TREE_TYPE (type), subclasses, bit_offset, + zero_width_bitfields); if (!num) return 0; @@ -2211,7 +2224,7 @@ classify_argument (machine_mode mode, co num = classify_argument (TYPE_MODE (TREE_TYPE (field)), TREE_TYPE (field), subclasses, - bit_offset); + bit_offset, zero_width_bitfields); if (!num) return 0; for (i = 0; i < num && i < words; i++) @@ -2231,7 +2244,7 @@ classify_argument (machine_mode mode, co X86_64_SSEUP_CLASS, everything should be passed in memory. */ if (classes[0] != X86_64_SSE_CLASS) - return 0; + return 0; for (i = 1; i < words; i++) if (classes[i] != X86_64_SSEUP_CLASS) @@ -2257,8 +2270,8 @@ classify_argument (machine_mode mode, co classes[i] = X86_64_SSE_CLASS; } - /* If X86_64_X87UP_CLASS isn't preceded by X86_64_X87_CLASS, - everything should be passed in memory. */ + /* If X86_64_X87UP_CLASS isn't preceded by X86_64_X87_CLASS, + everything should be passed in memory. */ if (classes[i] == X86_64_X87UP_CLASS && (classes[i - 1] != X86_64_X87_CLASS)) { @@ -2487,6 +2500,44 @@ classify_argument (machine_mode mode, co } } +/* Wrapper around classify_argument with the extra zero_width_bitfields + argument, to diagnose GCC 12.1 ABI differences for C. */ + +static int +classify_argument (machine_mode mode, const_tree type, + enum x86_64_reg_class classes[MAX_CLASSES], int bit_offset) +{ + int zero_width_bitfields = 0; + static bool warned = false; + int n = classify_argument (mode, type, classes, bit_offset, + zero_width_bitfields); + if (!zero_width_bitfields || warned || !warn_psabi) + return n; + enum x86_64_reg_class alt_classes[MAX_CLASSES]; + zero_width_bitfields = 2; + if (classify_argument (mode, type, alt_classes, bit_offset, + zero_width_bitfields) != n) + zero_width_bitfields = 3; + else + for (int i = 0; i < n; i++) + if (classes[i] != alt_classes[i]) + { + zero_width_bitfields = 3; + break; + } + if (zero_width_bitfields == 3) + { + warned = true; + const char *url + = CHANGES_ROOT_URL "gcc-12/changes.html#zero_width_bitfields"; + + inform (input_location, + "the ABI of passing C structures with zero-width bit-fields" + " has changed in GCC %{12.1%}", url); + } + return n; +} + /* Examine the argument and return set number of register required in each class. Return true iff parameter should be passed in memory. */ --- gcc/testsuite/gcc.target/i386/pr102024.c.jj 2021-12-15 14:52:55.970248045 +0100 +++ gcc/testsuite/gcc.target/i386/pr102024.c 2021-12-15 15:15:43.629881418 +0100 @@ -0,0 +1,12 @@ +/* PR target/102024 */ +/* { dg-do compile } */ + +struct S { float a; int : 0; float b; }; +void foo (struct S x); + +void +bar (void) +{ + struct S s = { 0.0f, 0.0f }; + foo (s); /* { dg-message "the ABI of passing C structures with zero-width bit-fields has changed in GCC 12.1" "" { target { ! ia32 } } } */ +} --- gcc/testsuite/g++.target/i386/pr102024.C.jj 2021-12-15 14:52:55.970248045 +0100 +++ gcc/testsuite/g++.target/i386/pr102024.C 2021-12-15 15:16:02.094619940 +0100 @@ -0,0 +1,12 @@ +// PR target/102024 +// { dg-do compile } + +struct S { float a; int : 0; float b; }; +void foo (struct S x); + +void +bar (void) +{ + struct S s = { 0.0f, 0.0f }; + foo (s); // { dg-bogus "the ABI of passing C structures with zero-width bit-fields has changed in GCC 12.1" } +}