From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 82814 invoked by alias); 25 Apr 2017 10:01:47 -0000 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Received: (qmail 82798 invoked by uid 89); 25 Apr 2017 10:01:46 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-11.9 required=5.0 tests=BAYES_00,GIT_PATCH_2,GIT_PATCH_3,RP_MATCHES_RCVD,SPF_HELO_PASS autolearn=ham version=3.3.2 spammy= X-HELO: mx1.redhat.com Received: from mx1.redhat.com (HELO mx1.redhat.com) (209.132.183.28) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Tue, 25 Apr 2017 10:01:44 +0000 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 mx1.redhat.com (Postfix) with ESMTPS id A7AFCC05AA61; Tue, 25 Apr 2017 10:01:45 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mx1.redhat.com A7AFCC05AA61 Authentication-Results: ext-mx08.extmail.prod.ext.phx2.redhat.com; dmarc=none (p=none dis=none) header.from=redhat.com Authentication-Results: ext-mx08.extmail.prod.ext.phx2.redhat.com; spf=pass smtp.mailfrom=jakub@redhat.com DKIM-Filter: OpenDKIM Filter v2.11.0 mx1.redhat.com A7AFCC05AA61 Received: from tucnak.zalov.cz (ovpn-116-29.ams2.redhat.com [10.36.116.29]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 46DA480797; Tue, 25 Apr 2017 10:01:45 +0000 (UTC) Received: from tucnak.zalov.cz (localhost [127.0.0.1]) by tucnak.zalov.cz (8.15.2/8.15.2) with ESMTP id v3PA1hpX001241; Tue, 25 Apr 2017 12:01:43 +0200 Received: (from jakub@localhost) by tucnak.zalov.cz (8.15.2/8.15.2/Submit) id v3PA1gUw001240; Tue, 25 Apr 2017 12:01:42 +0200 Date: Tue, 25 Apr 2017 10:04:00 -0000 From: Jakub Jelinek To: Richard Earnshaw , Ramana Radhakrishnan Cc: gcc-patches@gcc.gnu.org Subject: [AARCH64 ABI PATCH] Change AARCH64 ABI to match AAPCS, provide -Wpsabi notes (PR target/77728) Message-ID: <20170425100142.GV1809@tucnak> Reply-To: Jakub Jelinek MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline User-Agent: Mutt/1.7.1 (2016-10-04) X-IsSubscribed: yes X-SW-Source: 2017-04/txt/msg01142.txt.bz2 Hi! Similarly to the previous patch, just hopefully triggers less often, because 128-bit alignment is more rare. Ok for trunk/7.1 if it passes testing? 2017-04-25 Ramana Radhakrishnan Jakub Jelinek PR target/77728 * config/aarch64/aarch64.c (struct aarch64_fn_arg_alignment): New type. (aarch64_function_arg_alignment): Return aarch64_fn_arg_alignment struct. Ignore DECL_ALIGN of decls other than FIELD_DECL for the alignment computation, but return their maximum in warn_alignment. (aarch64_layout_arg): Adjust aarch64_function_arg_alignment caller. Emit a -Wpsabi note if warn_alignment is 16 bytes, but alignment is smaller. (aarch64_function_arg_boundary): Likewise. Simplify using MIN/MAX. (aarch64_gimplify_va_arg_expr): Adjust aarch64_function_arg_alignment caller. testsuite/ * g++.dg/abi/pr77728-2.C: New test. --- gcc/config/aarch64/aarch64.c.jj 2017-04-24 19:28:02.518970890 +0200 +++ gcc/config/aarch64/aarch64.c 2017-04-25 11:07:55.169532408 +0200 @@ -2256,33 +2256,58 @@ aarch64_vfp_is_call_candidate (cumulativ NULL); } -/* Given MODE and TYPE of a function argument, return the alignment in +struct aarch64_fn_arg_alignment +{ + /* Alignment for FIELD_DECLs in function arguments. */ + unsigned int alignment; + /* Alignment for decls other than FIELD_DECLs in function arguments. */ + unsigned int warn_alignment; +}; + +/* Given MODE and TYPE of a function argument, return a pair of alignments in bits. The idea is to suppress any stronger alignment requested by the user and opt for the natural alignment (specified in AAPCS64 \S 4.1). This is a helper function for local use only. */ -static unsigned int +static struct aarch64_fn_arg_alignment aarch64_function_arg_alignment (machine_mode mode, const_tree type) { + struct aarch64_fn_arg_alignment aa; + aa.alignment = 0; + aa.warn_alignment = 0; + if (!type) - return GET_MODE_ALIGNMENT (mode); + { + aa.alignment = GET_MODE_ALIGNMENT (mode); + return aa; + } + if (integer_zerop (TYPE_SIZE (type))) - return 0; + return aa; gcc_assert (TYPE_MODE (type) == mode); if (!AGGREGATE_TYPE_P (type)) - return TYPE_ALIGN (TYPE_MAIN_VARIANT (type)); + { + aa.alignment = TYPE_ALIGN (TYPE_MAIN_VARIANT (type)); + return aa; + } if (TREE_CODE (type) == ARRAY_TYPE) - return TYPE_ALIGN (TREE_TYPE (type)); - - unsigned int alignment = 0; + { + aa.alignment = TYPE_ALIGN (TREE_TYPE (type)); + return aa; + } for (tree field = TYPE_FIELDS (type); field; field = DECL_CHAIN (field)) - alignment = std::max (alignment, DECL_ALIGN (field)); + { + if (TREE_CODE (field) == FIELD_DECL) + aa.alignment = std::max (aa.alignment, DECL_ALIGN (field)); + else + aa.warn_alignment = std::max (aa.warn_alignment, DECL_ALIGN (field)); + } - return alignment; + return aa; } /* Layout a function argument according to the AAPCS64 rules. The rule @@ -2369,24 +2394,35 @@ aarch64_layout_arg (cumulative_args_t pc entirely general registers. */ if (allocate_ncrn && (ncrn + nregs <= NUM_ARG_REGS)) { - unsigned int alignment = aarch64_function_arg_alignment (mode, type); gcc_assert (nregs == 0 || nregs == 1 || nregs == 2); /* C.8 if the argument has an alignment of 16 then the NGRN is rounded up to the next even number. */ - if (nregs == 2 && alignment == 16 * BITS_PER_UNIT && ncrn % 2) + if (nregs == 2 && ncrn % 2) { - ++ncrn; - gcc_assert (ncrn + nregs <= NUM_ARG_REGS); + struct aarch64_fn_arg_alignment aa + = aarch64_function_arg_alignment (mode, type); + + if (aa.warn_alignment == 16 * BITS_PER_UNIT + && aa.alignment < aa.warn_alignment + && warn_psabi + && currently_expanding_gimple_stmt) + inform (input_location, + "parameter passing for argument of type %qT " + "changed in GCC 7.1", type); + else if (aa.alignment == 16 * BITS_PER_UNIT) + { + ++ncrn; + gcc_assert (ncrn + nregs <= NUM_ARG_REGS); + } } + /* NREGS can be 0 when e.g. an empty structure is to be passed. A reg is still generated for it, but the caller should be smart enough not to use it. */ if (nregs == 0 || nregs == 1 || GET_MODE_CLASS (mode) == MODE_INT) - { - pcum->aapcs_reg = gen_rtx_REG (mode, R0_REGNUM + ncrn); - } + pcum->aapcs_reg = gen_rtx_REG (mode, R0_REGNUM + ncrn); else { rtx par; @@ -2414,7 +2450,10 @@ aarch64_layout_arg (cumulative_args_t pc this argument and align the total size if necessary. */ on_stack: pcum->aapcs_stack_words = size / UNITS_PER_WORD; - if (aarch64_function_arg_alignment (mode, type) == 16 * BITS_PER_UNIT) + struct aarch64_fn_arg_alignment aa + = aarch64_function_arg_alignment (mode, type); + + if (aa.alignment == 16 * BITS_PER_UNIT) pcum->aapcs_stack_size = ROUND_UP (pcum->aapcs_stack_size, 16 / UNITS_PER_WORD); return; @@ -2505,13 +2544,17 @@ aarch64_function_arg_regno_p (unsigned r static unsigned int aarch64_function_arg_boundary (machine_mode mode, const_tree type) { - unsigned int alignment = aarch64_function_arg_alignment (mode, type); + struct aarch64_fn_arg_alignment aa + = aarch64_function_arg_alignment (mode, type); + aa.alignment = MIN (MAX (aa.alignment, PARM_BOUNDARY), STACK_BOUNDARY); + aa.warn_alignment + = MIN (MAX (aa.warn_alignment, PARM_BOUNDARY), STACK_BOUNDARY); + + if (warn_psabi && aa.warn_alignment > aa.alignment) + inform (input_location, "parameter passing for argument of type %qT " + "changed in GCC 7.1", type); - if (alignment < PARM_BOUNDARY) - alignment = PARM_BOUNDARY; - if (alignment > STACK_BOUNDARY) - alignment = STACK_BOUNDARY; - return alignment; + return aa.alignment; } /* For use by FUNCTION_ARG_PADDING (MODE, TYPE). @@ -10211,7 +10254,9 @@ aarch64_gimplify_va_arg_expr (tree valis stack = build3 (COMPONENT_REF, TREE_TYPE (f_stack), unshare_expr (valist), f_stack, NULL_TREE); size = int_size_in_bytes (type); - align = aarch64_function_arg_alignment (mode, type) / BITS_PER_UNIT; + struct aarch64_fn_arg_alignment aa + = aarch64_function_arg_alignment (mode, type); + align = aa.alignment / BITS_PER_UNIT; dw_align = false; adjust = 0; --- gcc/testsuite/g++.dg/abi/pr77728-2.C.jj 2017-04-25 10:54:08.396372117 +0200 +++ gcc/testsuite/g++.dg/abi/pr77728-2.C 2017-04-25 10:52:37.000000000 +0200 @@ -0,0 +1,171 @@ +// { dg-do compile { target { { aarch64-*-* } && c++11 } } } +// { dg-options "-Wpsabi" } + +#include + +template +struct alignas (16) A { char p[16]; }; + +A<0> v; + +template +struct B +{ + typedef A T; + int i, j, k, l; +}; + +struct C : public B<0> {}; +struct D {}; +struct E : public D, C {}; +struct F : public B<1> {}; +struct G : public F { static int y alignas (16); }; +struct H : public G {}; +struct I : public D { int z alignas (16); }; +struct J : public D { static int z alignas (16); int i, j, k, l; }; + +template +struct K : public D { typedef A T; int i, j; }; + +struct L { static int h alignas (16); int i, j, k, l; }; + +int +fn1 (int a, B<0> b) // { dg-message "note: parameter passing for argument of type \[^\n\r]* changed in GCC 7\.1" } +{ + return a + b.i; +} + +int +fn2 (int a, B<1> b) +{ + return a + b.i; +} + +int +fn3 (int a, L b) // { dg-message "note: parameter passing for argument of type \[^\n\r]* changed in GCC 7\.1" } +{ + return a + b.i; +} + +int +fn4 (int a, int b, int c, int d, int e, int f, int g, int h, int i, int j, int k, int l, int m, B<0> n, ...) +// { dg-message "note: parameter passing for argument of type \[^\n\r]* changed in GCC 7\.1" "" { target *-*-* } .-1 } +{ + va_list ap; + va_start (ap, n); + int x = va_arg (ap, int); + va_end (ap); + return x; +} + +int +fn5 (int a, int b, int c, int d, int e, int f, int g, int h, int i, int j, int k, int l, int m, B<1> n, ...) +{ + va_list ap; + va_start (ap, n); + int x = va_arg (ap, int); + va_end (ap); + return x; +} + +int +fn6 (int a, int b, int c, int d, int e, int f, int g, int h, int i, int j, int k, int l, int m, C n, ...) +{ + va_list ap; + va_start (ap, n); + int x = va_arg (ap, int); + va_end (ap); + return x; +} + +int +fn7 (int a, int b, int c, int d, int e, int f, int g, int h, int i, int j, int k, int l, int m, E n, ...) +{ + va_list ap; + va_start (ap, n); + int x = va_arg (ap, int); + va_end (ap); + return x; +} + +int +fn8 (int a, int b, int c, int d, int e, int f, int g, int h, int i, int j, int k, int l, int m, H n, ...) +{ + va_list ap; + va_start (ap, n); + int x = va_arg (ap, int); + va_end (ap); + return x; +} + +int +fn9 (int a, int b, int c, int d, int e, int f, int g, int h, int i, int j, int k, int l, int m, I n, ...) +{ + va_list ap; + va_start (ap, n); + int x = va_arg (ap, int); + va_end (ap); + return x; +} + +int +fn10 (int a, int b, int c, int d, int e, int f, int g, int h, int i, int j, int k, int l, int m, J n, ...) +// { dg-message "note: parameter passing for argument of type \[^\n\r]* changed in GCC 7\.1" "" { target *-*-* } .-1 } +{ + va_list ap; + va_start (ap, n); + int x = va_arg (ap, int); + va_end (ap); + return x; +} + +int +fn11 (int a, int b, int c, int d, int e, int f, int g, int h, int i, int j, int k, int l, int m, K<0> n, ...) +// { dg-message "note: parameter passing for argument of type \[^\n\r]* changed in GCC 7\.1" "" { target *-*-* } .-1 } +{ + va_list ap; + va_start (ap, n); + int x = va_arg (ap, int); + va_end (ap); + return x; +} + +int +fn12 (int a, int b, int c, int d, int e, int f, int g, int h, int i, int j, int k, int l, int m, K<2> n, ...) +{ + va_list ap; + va_start (ap, n); + int x = va_arg (ap, int); + va_end (ap); + return x; +} + +void +test () +{ + static B<0> b0; + static B<1> b1; + static L l; + static C c; + static E e; + static H h; + static I i; + static J j; + static K<0> k0; + static K<2> k2; + fn1 (1, b0); // { dg-message "note: parameter passing for argument of type \[^\n\r]* changed in GCC 7\.1" } + fn2 (1, b1); + fn3 (1, l); // { dg-message "note: parameter passing for argument of type \[^\n\r]* changed in GCC 7\.1" } + fn4 (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, b0, 1, 2, 3, 4); + // { dg-message "note: parameter passing for argument of type \[^\n\r]* changed in GCC 7\.1" "" { target *-*-* } .-1 } + fn5 (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, b1, 1, 2, 3, 4); + fn6 (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, c, 1, 2, 3, 4); + fn7 (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, e, 1, 2, 3, 4); + fn8 (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, h, 1, 2, 3, 4); + fn9 (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, i, 1, 2, 3, 4); + fn10 (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, j, 1, 2, 3, 4); + // { dg-message "note: parameter passing for argument of type \[^\n\r]* changed in GCC 7\.1" "" { target *-*-* } .-1 } + fn11 (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, k0, 1, 2, 3, 4); + // { dg-message "note: parameter passing for argument of type \[^\n\r]* changed in GCC 7\.1" "" { target *-*-* } .-1 } + fn12 (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, k2, 1, 2, 3, 4); +} Jakub