From patchwork Fri Nov 26 05:28:50 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Siddhesh Poyarekar X-Patchwork-Id: 48175 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 4A40F3858038 for ; Fri, 26 Nov 2021 05:33:16 +0000 (GMT) X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from dragonfly.birch.relay.mailchannels.net (dragonfly.birch.relay.mailchannels.net [23.83.209.51]) by sourceware.org (Postfix) with ESMTPS id 722FF3858439 for ; Fri, 26 Nov 2021 05:29:25 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 722FF3858439 Authentication-Results: sourceware.org; dmarc=none (p=none dis=none) header.from=gotplt.org Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=gotplt.org X-Sender-Id: dreamhost|x-authsender|siddhesh@gotplt.org Received: from relay.mailchannels.net (localhost [127.0.0.1]) by relay.mailchannels.net (Postfix) with ESMTP id CA5342C1351; Fri, 26 Nov 2021 05:29:23 +0000 (UTC) Received: from pdx1-sub0-mail-a305.dreamhost.com (unknown [127.0.0.6]) (Authenticated sender: dreamhost) by relay.mailchannels.net (Postfix) with ESMTPA id 5E8452C1428; Fri, 26 Nov 2021 05:29:23 +0000 (UTC) X-Sender-Id: dreamhost|x-authsender|siddhesh@gotplt.org Received: from pdx1-sub0-mail-a305.dreamhost.com (pop.dreamhost.com [64.90.62.162]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384) by 100.124.138.98 (trex/6.4.3); Fri, 26 Nov 2021 05:29:23 +0000 X-MC-Relay: Neutral X-MailChannels-SenderId: dreamhost|x-authsender|siddhesh@gotplt.org X-MailChannels-Auth-Id: dreamhost X-Keen-Language: 20717bb866f5d42d_1637904563673_2508787475 X-MC-Loop-Signature: 1637904563673:3333928515 X-MC-Ingress-Time: 1637904563673 Received: from rhbox.intra.reserved-bit.com (unknown [1.186.223.60]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) (Authenticated sender: siddhesh@gotplt.org) by pdx1-sub0-mail-a305.dreamhost.com (Postfix) with ESMTPSA id 4J0jwd53fBz1QQ; Thu, 25 Nov 2021 21:29:21 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha1; c=relaxed/relaxed; d=gotplt.org; s=gotplt.org; t=1637904563; bh=P/MijYKZL+uS7m0NQrYEyp6OfKA=; h=From:To:Cc:Subject:Date:Content-Transfer-Encoding; b=io5vRxG6n6qMvtjWXbBl0ib8nMkOEhO8mOVueb0gmebSIaw/sHrzEVFn09URa57US OBDY6/82Ib6wTqOayP4q0ndcHvg0vQSzpsV8XqulvLBzDY/GQalNPkrtFBewpK0K+8 PPwU5DWufC/I/UfTdLpeUbrm7Frc7+1+MyhcUssQ= From: Siddhesh Poyarekar To: gcc-patches@gcc.gnu.org Subject: [PATCH v3 7/8] tree-object-size: Handle GIMPLE_CALL Date: Fri, 26 Nov 2021 10:58:50 +0530 Message-Id: <20211126052851.2176408-8-siddhesh@gotplt.org> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20211126052851.2176408-1-siddhesh@gotplt.org> References: <20211109190137.1107736-1-siddhesh@gotplt.org> <20211126052851.2176408-1-siddhesh@gotplt.org> MIME-Version: 1.0 X-Spam-Status: No, score=-3038.7 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, RCVD_IN_DNSWL_NONE, RCVD_IN_MSPIKE_H2, 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: , Cc: jakub@redhat.com Errors-To: gcc-patches-bounces+patchwork=sourceware.org@gcc.gnu.org Sender: "Gcc-patches" Handle non-constant expressions in GIMPLE_CALL arguments. Also handle alloca. gcc/ChangeLog: * tree-object-size.c (alloc_object_size): Make and return non-constant size expression. (call_object_size): Return expression or unknown based on whether dynamic object size is requested. gcc/testsuite/ChangeLog: * gcc.dg/builtin-dynamic-object-size-0.c: Add new tests. * gcc.dg/builtin-object-size-1.c (test1) [__builtin_object_size]: Alter expected result for dynamic object size. * gcc.dg/builtin-object-size-2.c (test1) [__builtin_object_size]: Likewise. * gcc.dg/builtin-object-size-3.c (test1) [__builtin_object_size]: Likewise. * gcc.dg/builtin-object-size-4.c (test1) [__builtin_object_size]: Likewise. Signed-off-by: Siddhesh Poyarekar --- .../gcc.dg/builtin-dynamic-object-size-0.c | 227 +++++++++++++++++- gcc/testsuite/gcc.dg/builtin-object-size-1.c | 7 + gcc/testsuite/gcc.dg/builtin-object-size-2.c | 14 ++ gcc/testsuite/gcc.dg/builtin-object-size-3.c | 7 + gcc/testsuite/gcc.dg/builtin-object-size-4.c | 14 ++ gcc/tree-object-size.c | 22 +- 6 files changed, 282 insertions(+), 9 deletions(-) diff --git a/gcc/testsuite/gcc.dg/builtin-dynamic-object-size-0.c b/gcc/testsuite/gcc.dg/builtin-dynamic-object-size-0.c index ce0f4eb17f3..2db0e0d1aa2 100644 --- a/gcc/testsuite/gcc.dg/builtin-dynamic-object-size-0.c +++ b/gcc/testsuite/gcc.dg/builtin-dynamic-object-size-0.c @@ -4,12 +4,71 @@ typedef __SIZE_TYPE__ size_t; #define abort __builtin_abort +void * +__attribute__ ((alloc_size (1))) +__attribute__ ((__nothrow__ , __leaf__)) +__attribute__ ((noinline)) +alloc_func (size_t sz) +{ + return __builtin_malloc (sz); +} + +void * +__attribute__ ((alloc_size (1, 2))) +__attribute__ ((__nothrow__ , __leaf__)) +__attribute__ ((noinline)) +calloc_func (size_t cnt, size_t sz) +{ + return __builtin_calloc (cnt, sz); +} + +void * +__attribute__ ((noinline)) +unknown_allocator (size_t cnt, size_t sz) +{ + return __builtin_calloc (cnt, sz); +} + +size_t +__attribute__ ((noinline)) +test_unknown (size_t cnt, size_t sz) +{ + void *ret = unknown_allocator (cnt, sz); + return __builtin_dynamic_object_size (ret, 0); +} + +/* Malloc-like allocator. */ + +size_t +__attribute__ ((noinline)) +test_malloc (size_t sz) +{ + void *ret = alloc_func (sz); + return __builtin_dynamic_object_size (ret, 0); +} + +size_t +__attribute__ ((noinline)) +test_builtin_malloc (size_t sz) +{ + void *ret = __builtin_malloc (sz); + return __builtin_dynamic_object_size (ret, 0); +} + +size_t +__attribute__ ((noinline)) +test_builtin_malloc_cond (int cond) +{ + void *ret = __builtin_malloc (cond ? 32 : 64); + return __builtin_dynamic_object_size (ret, 0); +} + size_t __attribute__ ((noinline)) test_builtin_malloc_condphi (int cond) { void *ret; - + if (cond) ret = __builtin_malloc (32); else @@ -18,6 +77,79 @@ test_builtin_malloc_condphi (int cond) return __builtin_dynamic_object_size (ret, 0); } +size_t +__attribute__ ((noinline)) +test_builtin_malloc_condphi2 (int cond, size_t in) +{ + void *ret; + + if (cond) + ret = __builtin_malloc (in); + else + ret = __builtin_malloc (64); + + return __builtin_dynamic_object_size (ret, 0); +} + +size_t +__attribute__ ((noinline)) +test_builtin_malloc_condphi3 (int cond, size_t in, size_t in2) +{ + void *ret; + + if (cond) + ret = __builtin_malloc (in); + else + ret = __builtin_malloc (in2); + + return __builtin_dynamic_object_size (ret, 0); +} + +size_t +__attribute__ ((noinline)) +test_builtin_malloc_condphi4 (size_t sz, int cond) +{ + char *a = __builtin_malloc (sz); + char b[sz / 2]; + + return __builtin_dynamic_object_size (cond ? b : (void *) &a, 0); +} + +size_t +__attribute__ ((noinline)) +test_builtin_malloc_condphi5 (size_t sz, int cond, char *c) +{ + char *a = __builtin_malloc (sz); + + return __builtin_dynamic_object_size (cond ? c : (void *) &a, 0); +} + +/* Calloc-like allocator. */ + +size_t +__attribute__ ((noinline)) +test_calloc (size_t cnt, size_t sz) +{ + void *ret = calloc_func (cnt, sz); + return __builtin_dynamic_object_size (ret, 0); +} + +size_t +__attribute__ ((noinline)) +test_builtin_calloc (size_t cnt, size_t sz) +{ + void *ret = __builtin_calloc (cnt, sz); + return __builtin_dynamic_object_size (ret, 0); +} + +size_t +__attribute__ ((noinline)) +test_builtin_calloc_cond (int cond1, int cond2) +{ + void *ret = __builtin_calloc (cond1 ? 32 : 64, cond2 ? 1024 : 16); + return __builtin_dynamic_object_size (ret, 0); +} + size_t __attribute__ ((noinline)) test_builtin_calloc_condphi (size_t cnt, size_t sz, int cond) @@ -33,6 +165,47 @@ test_builtin_calloc_condphi (size_t cnt, size_t sz, int cond) return __builtin_dynamic_object_size (cond ? ch : (void *) &bin, 0); } +/* Passthrough functions. */ + +size_t +__attribute__ ((noinline)) +test_passthrough (size_t sz, char *in) +{ + char *bin = __builtin_malloc (sz); + char *dest = __builtin_memcpy (bin, in, sz); + + return __builtin_dynamic_object_size (dest, 0); +} + +size_t +__attribute__ ((noinline)) +test_passthrough_nonssa (char *in) +{ + char bin[__builtin_strlen (in) + 1]; + char *dest = __builtin_memcpy (bin, in, __builtin_strlen (in) + 1); + + return __builtin_dynamic_object_size (dest, 0); +} + +/* Variable length arrays. */ +size_t +__attribute__ ((noinline)) +test_dynarray (size_t sz) +{ + char bin[sz]; + + return __builtin_dynamic_object_size (bin, 0); +} + +size_t +__attribute__ ((noinline)) +test_dynarray_cond (int cond) +{ + char bin[cond ? 8 : 16]; + + return __builtin_dynamic_object_size (bin, 0); +} + size_t __attribute__ ((noinline)) test_deploop (size_t sz, size_t cond) @@ -41,7 +214,7 @@ test_deploop (size_t sz, size_t cond) for (size_t i = 0; i < sz; i++) if (i == cond) - bin = __builtin_alloca (64); + bin = __builtin_alloca (sz); return __builtin_dynamic_object_size (bin, 0); } @@ -64,12 +237,62 @@ unsigned nfails = 0; int main (int argc, char **argv) { + size_t outsz = test_unknown (32, 42); + if (outsz != -1 && outsz != 32) + FAIL (); + if (test_malloc (2048) != 2048) + FAIL (); + if (test_builtin_malloc (2048) != 2048) + FAIL (); + if (test_builtin_malloc_cond (1) != 32) + FAIL (); + if (test_builtin_malloc_cond (0) != 64) + FAIL (); if (test_builtin_malloc_condphi (1) != 32) FAIL (); if (test_builtin_malloc_condphi (0) != 64) FAIL (); + if (test_builtin_malloc_condphi2 (1, 128) != 128) + FAIL (); + if (test_builtin_malloc_condphi2 (0, 128) != 64) + FAIL (); + if (test_builtin_malloc_condphi3 (1, 128, 256) != 128) + FAIL (); + if (test_builtin_malloc_condphi3 (0, 128, 256) != 256) + FAIL (); + if (test_builtin_malloc_condphi4 (128, 1) != 64) + FAIL (); + if (test_builtin_malloc_condphi4 (128, 0) != sizeof (void *)) + FAIL (); + if (test_builtin_malloc_condphi5 (128, 0, argv[0]) != -1) + FAIL (); + if (test_calloc (2048, 4) != 2048 * 4) + FAIL (); + if (test_builtin_calloc (2048, 8) != 2048 * 8) + FAIL (); + if (test_builtin_calloc_cond (0, 0) != 64 * 16) + FAIL (); + if (test_builtin_calloc_cond (1, 1) != 32 * 1024) + FAIL (); + if (test_builtin_calloc_condphi (128, 1, 1) != 128) + FAIL (); if (test_builtin_calloc_condphi (128, 1, 0) == 128) FAIL (); + if (test_builtin_calloc_condphi (128, 1, 0) == -1) + FAIL (); + if (test_passthrough (__builtin_strlen (argv[0]) + 1, argv[0]) + != __builtin_strlen (argv[0]) + 1) + FAIL (); + if (test_passthrough_nonssa (argv[0]) != __builtin_strlen (argv[0]) + 1) + FAIL (); + if (test_dynarray (__builtin_strlen (argv[0])) != __builtin_strlen (argv[0])) + FAIL (); + if (test_dynarray_cond (0) != 16) + FAIL (); + if (test_dynarray_cond (1) != 8) + FAIL (); + if (test_deploop (128, 4) != 128) + FAIL (); if (test_deploop (128, 129) != 32) FAIL (); if (test_parmsz_simple (argv[0], __builtin_strlen (argv[0]) + 1) diff --git a/gcc/testsuite/gcc.dg/builtin-object-size-1.c b/gcc/testsuite/gcc.dg/builtin-object-size-1.c index 265c87ed6fb..06d442796cb 100644 --- a/gcc/testsuite/gcc.dg/builtin-object-size-1.c +++ b/gcc/testsuite/gcc.dg/builtin-object-size-1.c @@ -135,10 +135,17 @@ test1 (void *q, int x) abort (); if (__builtin_object_size (&extb[5], 0) != sizeof (extb) - 5) abort (); +#ifdef __builtin_object_size + if (__builtin_object_size (var, 0) != x + 10) + abort (); + if (__builtin_object_size (var + 10, 0) != x) + abort (); +#else if (__builtin_object_size (var, 0) != (size_t) -1) abort (); if (__builtin_object_size (var + 10, 0) != (size_t) -1) abort (); +#endif if (__builtin_object_size (&var[5], 0) != (size_t) -1) abort (); if (__builtin_object_size (zerol, 0) != 0) diff --git a/gcc/testsuite/gcc.dg/builtin-object-size-2.c b/gcc/testsuite/gcc.dg/builtin-object-size-2.c index 5051fea47c3..2364f2d6afd 100644 --- a/gcc/testsuite/gcc.dg/builtin-object-size-2.c +++ b/gcc/testsuite/gcc.dg/builtin-object-size-2.c @@ -137,16 +137,30 @@ test1 (void *q, int x) abort (); if (__builtin_object_size (&extc[5].c[3], 1) != (size_t) -1) abort (); +#ifdef __builtin_object_size + if (__builtin_object_size (var, 1) != x + 10) + abort (); + if (__builtin_object_size (var + 10, 1) != x) + abort (); +#else if (__builtin_object_size (var, 1) != (size_t) -1) abort (); if (__builtin_object_size (var + 10, 1) != (size_t) -1) abort (); +#endif if (__builtin_object_size (&var[5], 1) != (size_t) -1) abort (); +#ifdef __builtin_object_size + if (__builtin_object_size (vara, 1) != (x + 10) * sizeof (struct A)) + abort (); + if (__builtin_object_size (vara + 10, 1) != x * sizeof (struct A)) + abort (); +#else if (__builtin_object_size (vara, 1) != (size_t) -1) abort (); if (__builtin_object_size (vara + 10, 1) != (size_t) -1) abort (); +#endif if (__builtin_object_size (&vara[5], 1) != (size_t) -1) abort (); if (__builtin_object_size (&vara[0].a, 1) != sizeof (vara[0].a)) diff --git a/gcc/testsuite/gcc.dg/builtin-object-size-3.c b/gcc/testsuite/gcc.dg/builtin-object-size-3.c index 1d92627266b..753ee4a1a4f 100644 --- a/gcc/testsuite/gcc.dg/builtin-object-size-3.c +++ b/gcc/testsuite/gcc.dg/builtin-object-size-3.c @@ -140,10 +140,17 @@ test1 (void *q, int x) abort (); if (__builtin_object_size (&extb[5], 2) != sizeof (extb) - 5) abort (); +#ifdef __builtin_object_size + if (__builtin_object_size (var, 2) != x + 10) + abort (); + if (__builtin_object_size (var + 10, 2) != x) + abort (); +#else if (__builtin_object_size (var, 2) != 0) abort (); if (__builtin_object_size (var + 10, 2) != 0) abort (); +#endif if (__builtin_object_size (&var[5], 2) != 0) abort (); if (__builtin_object_size (zerol, 2) != 0) diff --git a/gcc/testsuite/gcc.dg/builtin-object-size-4.c b/gcc/testsuite/gcc.dg/builtin-object-size-4.c index 9da3537a5f7..c383385e060 100644 --- a/gcc/testsuite/gcc.dg/builtin-object-size-4.c +++ b/gcc/testsuite/gcc.dg/builtin-object-size-4.c @@ -150,16 +150,30 @@ test1 (void *q, int x) abort (); if (__builtin_object_size (&extc[5].c[3], 3) != 0) abort (); +#ifdef __builtin_object_size + if (__builtin_object_size (var, 3) != x + 10) + abort (); + if (__builtin_object_size (var + 10, 3) != x) + abort (); +#else if (__builtin_object_size (var, 3) != 0) abort (); if (__builtin_object_size (var + 10, 3) != 0) abort (); +#endif if (__builtin_object_size (&var[5], 3) != 0) abort (); +#ifdef __builtin_object_size + if (__builtin_object_size (vara, 3) != (x + 10) * sizeof (struct A)) + abort (); + if (__builtin_object_size (vara + 10, 3) != x * sizeof (struct A)) + abort (); +#else if (__builtin_object_size (vara, 3) != 0) abort (); if (__builtin_object_size (vara + 10, 3) != 0) abort (); +#endif if (__builtin_object_size (&vara[5], 3) != 0) abort (); if (__builtin_object_size (&vara[0].a, 3) != sizeof (vara[0].a)) diff --git a/gcc/tree-object-size.c b/gcc/tree-object-size.c index 48b1ec6e26a..f03714c4f18 100644 --- a/gcc/tree-object-size.c +++ b/gcc/tree-object-size.c @@ -755,7 +755,8 @@ alloc_object_size (const gcall *call, int object_size_type) gcc_assert (is_gimple_call (call)); tree calltype; - if (tree callfn = gimple_call_fndecl (call)) + tree callfn = gimple_call_fndecl (call); + if (callfn) calltype = TREE_TYPE (callfn); else calltype = gimple_call_fntype (call); @@ -775,12 +776,13 @@ alloc_object_size (const gcall *call, int object_size_type) if (TREE_CHAIN (p)) arg2 = TREE_INT_CST_LOW (TREE_VALUE (TREE_CHAIN (p)))-1; } + else if (gimple_call_builtin_p (call, BUILT_IN_NORMAL) + && callfn && ALLOCA_FUNCTION_CODE_P (DECL_FUNCTION_CODE (callfn))) + arg1 = 0; - if (arg1 < 0 || arg1 >= (int)gimple_call_num_args (call) - || TREE_CODE (gimple_call_arg (call, arg1)) != INTEGER_CST - || (arg2 >= 0 - && (arg2 >= (int)gimple_call_num_args (call) - || TREE_CODE (gimple_call_arg (call, arg2)) != INTEGER_CST))) + /* Non-const arguments are OK here, let the caller handle constness. */ + if (arg1 < 0 || arg1 >= (int) gimple_call_num_args (call) + || arg2 >= (int) gimple_call_num_args (call)) return size_unknown (object_size_type); tree bytes = NULL_TREE; @@ -791,7 +793,10 @@ alloc_object_size (const gcall *call, int object_size_type) else if (arg1 >= 0) bytes = fold_convert (sizetype, gimple_call_arg (call, arg1)); - return bytes; + if (bytes) + return STRIP_NOPS (bytes); + + return size_unknown (object_size_type); } @@ -1250,6 +1255,9 @@ call_object_size (struct object_size_info *osi, tree ptr, gcall *call) gcc_assert (osi->pass == 0); tree bytes = alloc_object_size (call, object_size_type); + if (!(object_size_type & OST_DYNAMIC) && TREE_CODE (bytes) != INTEGER_CST) + bytes = size_unknown (object_size_type); + object_sizes_set (osi, varno, bytes, bytes); }