From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: by sourceware.org (Postfix, from userid 7810) id 35BCA395C000; Wed, 16 Nov 2022 13:44:18 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 35BCA395C000 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1668606258; bh=Ed1lMte/DGUR61guajbHz6czl0j8mz5+Dj8yGcesZx4=; h=From:To:Subject:Date:From; b=apsTzIOZ0eF/j8Y15WNNVUUiaDz2pzxC4QiNPBn7ypXc0YlhUy2cBrMQpAuLBSFO5 XfldOhxiozlIZe/0+lLeERg5jjHUuBmTaVVU1AcFAFy4TJayjVDuBsifidgeIBNImS 1zxGvCcYqegvU5KAGL4MkiDvTa/xo3mJVnY0Ic58= Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: Alex Coplan To: gcc-cvs@gcc.gnu.org Subject: [gcc(refs/vendors/ARM/heads/morello)] convert.c: Add logic for widening conversions of capabilities X-Act-Checkin: gcc X-Git-Author: Victor Do Nascimento X-Git-Refname: refs/vendors/ARM/heads/morello X-Git-Oldrev: c5fc2e2b80a4b192ffdbaf416033c7c62c9fef01 X-Git-Newrev: c69da8925365a04afdcc222e98235e8b7459756d Message-Id: <20221116134418.35BCA395C000@sourceware.org> Date: Wed, 16 Nov 2022 13:44:18 +0000 (GMT) List-Id: https://gcc.gnu.org/g:c69da8925365a04afdcc222e98235e8b7459756d commit c69da8925365a04afdcc222e98235e8b7459756d Author: Victor Do Nascimento Date: Wed Nov 16 13:41:56 2022 +0000 convert.c: Add logic for widening conversions of capabilities This patch provides a pathway for conversion of capabilities to __int128 types, extending extracted capability values according to the underlying capability type. As a direct conversion from capability to __int128 would imply the exposure of capability metadata, an indirect conversion path via noncapability_type is provided, dropping capability metadata prior to converting to the final integer type. Further logic is also added to prevent the folding of the resulting 2-step conversion back to the original expression during optimization. Pointers are sign extended to follow GCC's existing implementation-defined choice for the result of converting a pointer to a wider integer type, while __intcap values are extended in accordance with their signedness. This fixes an ICE seen in libstdc++ 25_algorithms/{fill|generate}_n/87982_neg.cc tests. gcc/ChangeLog: * gcc/convert.c (convert_to_integer_1): add capability -> __int128 conversion logic. * gcc/match.pd: Prevent folding of metadata-exposing widening conversions for capabilities. gcc/testsuite/ChangeLog: * g++.target/aarch64/morello/int128-conv-semantics.C: New. * gcc.target/aarch64/morello/int128-conv-semantics.c: Likewise. Diff: --- gcc/convert.c | 42 ++++++++++--- gcc/match.pd | 4 +- .../aarch64/morello/int128-conv-semantics.C | 73 ++++++++++++++++++++++ .../aarch64/morello/int128-conv-semantics.c | 72 +++++++++++++++++++++ 4 files changed, 180 insertions(+), 11 deletions(-) diff --git a/gcc/convert.c b/gcc/convert.c index e076be027f4..8bcb58489d0 100644 --- a/gcc/convert.c +++ b/gcc/convert.c @@ -514,6 +514,8 @@ convert_to_integer_1 (tree type, tree expr, bool dofold) unsigned int outprec = element_precision (type); location_t loc = EXPR_LOCATION (expr); + gcc_assert (!capability_type_p (type)); + /* An INTEGER_TYPE cannot be incomplete, but an ENUMERAL_TYPE can be. Consider `enum E = { a, b = (enum E) 3 };'. */ if (!COMPLETE_TYPE_P (type)) @@ -688,17 +690,37 @@ convert_to_integer_1 (tree type, tree expr, bool dofold) && !TREE_OVERFLOW (tree_strip_any_location_wrapper (expr))) return build_int_cst (type, 0); - /* Convert to an unsigned integer of the correct width first, and from - there widen/truncate to the required type. Some targets support the - coexistence of multiple valid pointer sizes, so fetch the one we need + /* Convert to integer of the correct width first, and from there + widen/truncate to the required type. In the case of intcap + values, the signedness of the intermediate type mirrors that + of the original intcap type. In the case of capabilities, + GCC's implementation-defined behavior of sign-extending + pointers is preserved. Some targets support the coexistence + of multiple valid pointer sizes, so fetch the one we need from the type. */ - if (!dofold) - return build1 (CONVERT_EXPR, type, expr); - expr = fold_build1 (CONVERT_EXPR, - lang_hooks.types.type_for_size - (TYPE_NONCAP_PRECISION (intype), 0), - expr); - return fold_convert (type, expr); + { + int unsigned_p = INTCAP_TYPE_P (intype) ? TYPE_UNSIGNED (intype) : 0; + if (!dofold) + { + /* Enable conversion from capability and __intcap to __int128 + via initial conversion to (unsigned) long int. */ + if (capability_type_p (intype) + && INTEGRAL_TYPE_P (type) + && outprec > TYPE_NONCAP_PRECISION (intype)) + { + expr = build1 (CONVERT_EXPR, + lang_hooks.types.type_for_size + (TYPE_NONCAP_PRECISION (intype), unsigned_p), + expr); + } + return build1 (CONVERT_EXPR, type, expr); + } + expr = fold_build1 (CONVERT_EXPR, + lang_hooks.types.type_for_size + (TYPE_NONCAP_PRECISION (intype), unsigned_p), + expr); + return fold_convert (type, expr); + } case INTEGER_TYPE: case ENUMERAL_TYPE: diff --git a/gcc/match.pd b/gcc/match.pd index fa196c23ba9..07640ffe0a9 100644 --- a/gcc/match.pd +++ b/gcc/match.pd @@ -3188,6 +3188,7 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) (with { tree inside_type = TREE_TYPE (@0); + bool inside_iscap = capability_type_p (inside_type); tree inter_type = TREE_TYPE (@1); int inside_int = INTEGRAL_TYPE_P (inside_type); int inside_ptr = POINTER_TYPE_P (inside_type); @@ -3262,7 +3263,8 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) && ((inter_unsignedp && inter_prec > inside_prec) == (final_unsignedp && final_prec > inter_prec)) && ! (inside_ptr && inter_prec != final_prec) - && ! (final_ptr && inside_prec != inter_prec)) + && ! (final_ptr && inside_prec != inter_prec) + && ! (inside_iscap && final_prec > inside_prec)) (ocvt @0)) /* A truncation to an unsigned type (a zero-extension) should be diff --git a/gcc/testsuite/g++.target/aarch64/morello/int128-conv-semantics.C b/gcc/testsuite/g++.target/aarch64/morello/int128-conv-semantics.C new file mode 100644 index 00000000000..f464f4cb5ac --- /dev/null +++ b/gcc/testsuite/g++.target/aarch64/morello/int128-conv-semantics.C @@ -0,0 +1,73 @@ +/* Check that __int128 conversion semantics are implemented + correctly in the front and middle-end. */ +/* { dg-do assemble } */ +/* { dg-additional-options "-save-temps=obj -fdump-tree-original -fpermissive" } */ +/* { dg-final { check-function-bodies "**" "" { {-O[123s]} } } } */ +/* { dg-require-effective-target cheri_capability_pure } */ +/* { dg-skip-if "" { *-*-* } { -fuse-linker-plugin } } */ + +/* +** _Z18uintcap_to_uint128u11__uintcap_t: +** mov x1, 0 +** ret +*/ +unsigned __int128 uintcap_to_uint128(unsigned __intcap a1) +{ + return a1; +} +/* { dg-final { scan-tree-dump-times { = \(__int128 unsigned\) \(long unsigned int\) a1;} 1 "original" } } */ + +/* +** _Z17intcap_to_uint128u10__intcap_t: +** asr x1, x0, 63 +** ret +*/ +unsigned __int128 intcap_to_uint128(__intcap a2) +{ + return a2; +} +/* { dg-final { scan-tree-dump-times { = \(__int128 unsigned\) \(long int\) a2;} 1 "original" } } */ + +/* +** _Z14ptr_to_uint128Pi: +** asr x1, x0, 63 +** ret +*/ +unsigned __int128 ptr_to_uint128(int *a3) +{ + return a3; /* { dg-warning \[-fpermissive\] } */ +} +/* { dg-final { scan-tree-dump-times { = \(__int128 unsigned\) \(long int\) a3;} 1 "original" } } */ + +/* +** _Z17uintcap_to_int128u11__uintcap_t: +** mov x1, 0 +** ret +*/ + __int128 uintcap_to_int128(unsigned __intcap a4) + { + return a4; + } +/* { dg-final { scan-tree-dump-times { = \(__int128\) \(long unsigned int\) a4;} 1 "original" } } */ + +/* +** _Z16intcap_to_int128u10__intcap_t: +** asr x1, x0, 63 +** ret +*/ + __int128 intcap_to_int128(__intcap a5) + { + return a5; + } +/* { dg-final { scan-tree-dump-times { = \(__int128\) \(long int\) a5;} 1 "original" } } */ + +/* +** _Z13ptr_to_int128Pi: +** asr x1, x0, 63 +** ret +*/ + __int128 ptr_to_int128(int *a6) + { + return a6; /* { dg-warning \[-fpermissive\] } */ + } +/* { dg-final { scan-tree-dump-times { = \(__int128\) \(long int\) a6;} 1 "original" } } */ diff --git a/gcc/testsuite/gcc.target/aarch64/morello/int128-conv-semantics.c b/gcc/testsuite/gcc.target/aarch64/morello/int128-conv-semantics.c new file mode 100644 index 00000000000..c88dad5d6a1 --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/morello/int128-conv-semantics.c @@ -0,0 +1,72 @@ +/* Check that __int128 conversion semantics are implemented + correctly in the front and middle-end. */ +/* { dg-do assemble } */ +/* { dg-additional-options "-save-temps -fdump-tree-original" } */ +/* { dg-final { check-function-bodies "**" "" { {-O[123s]} } } } */ +/* { dg-require-effective-target cheri_capability_pure } */ + +/* +** uintcap_to_uint128: +** mov x1, 0 +** ret +*/ +unsigned __int128 uintcap_to_uint128(unsigned __intcap a1) +{ + return a1; +} +/* { dg-final { scan-tree-dump-times {return \(__int128 unsigned\) \(long unsigned int\) a1;} 1 "original" } } */ + +/* +** intcap_to_uint128: +** asr x1, x0, 63 +** ret +*/ +unsigned __int128 intcap_to_uint128(__intcap a2) +{ + return a2; +} +/* { dg-final { scan-tree-dump-times {return \(__int128 unsigned\) \(long int\) a2;} 1 "original" } } */ + +/* +** ptr_to_uint128: +** asr x1, x0, 63 +** ret +*/ +unsigned __int128 ptr_to_uint128(int *a3) +{ + return a3; /* { dg-warning \[-fpermissive\] } */ +} +/* { dg-final { scan-tree-dump-times {return \(__int128 unsigned\) \(long int\) a3;} 1 "original" } } */ + +/* +** uintcap_to_int128: +** mov x1, 0 +** ret +*/ + __int128 uintcap_to_int128(unsigned __intcap a4) + { + return a4; + } +/* { dg-final { scan-tree-dump-times {return \(__int128\) \(long unsigned int\) a4;} 1 "original" } } */ + +/* +** intcap_to_int128: +** asr x1, x0, 63 +** ret +*/ + __int128 intcap_to_int128(__intcap a5) + { + return a5; + } +/* { dg-final { scan-tree-dump-times {return \(__int128\) \(long int\) a5;} 1 "original" } } */ + +/* +** ptr_to_int128: +** asr x1, x0, 63 +** ret +*/ + __int128 ptr_to_int128(int *a6) + { + return a6; /* { dg-warning \[-fpermissive\] } */ + } +/* { dg-final { scan-tree-dump-times {return \(__int128\) \(long int\) a6;} 1 "original" } } */