From patchwork Fri Nov 26 05:28:51 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Siddhesh Poyarekar X-Patchwork-Id: 48176 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 DDE303858036 for ; Fri, 26 Nov 2021 05:33:51 +0000 (GMT) X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from donkey.elm.relay.mailchannels.net (donkey.elm.relay.mailchannels.net [23.83.212.49]) by sourceware.org (Postfix) with ESMTPS id 1C7333858017 for ; Fri, 26 Nov 2021 05:29:28 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 1C7333858017 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 9B5B81215F6; Fri, 26 Nov 2021 05:29:27 +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 00BE41215DA; Fri, 26 Nov 2021 05:29:25 +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.99.149.17 (trex/6.4.3); Fri, 26 Nov 2021 05:29:27 +0000 X-MC-Relay: Neutral X-MailChannels-SenderId: dreamhost|x-authsender|siddhesh@gotplt.org X-MailChannels-Auth-Id: dreamhost X-Unite-Minister: 5640981511f92a31_1637904567126_3548022977 X-MC-Loop-Signature: 1637904567126:4011973441 X-MC-Ingress-Time: 1637904567125 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 4J0jwh0RYlz3C; Thu, 25 Nov 2021 21:29:23 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha1; c=relaxed/relaxed; d=gotplt.org; s=gotplt.org; t=1637904565; bh=jl0TWg6VHhulHW+kvBG3410SCus=; h=From:To:Cc:Subject:Date:Content-Transfer-Encoding; b=k+iKho757DqSp8EEMcGGmE9ubo5T160pBEkx1PD1bHENZhb4KimmMgVNAhqw8cQS6 GEhnXyCiH89SzLrOWZNBCYiuqs9Vvwu0ekJoldO/+ALjSpyDZoddk+0XWbVTRsWD7+ 9aIEmJcEAIUrLvPU8YQ4bOzkcR+kfr9Iue6GihQ4= From: Siddhesh Poyarekar To: gcc-patches@gcc.gnu.org Subject: [PATCH v3 8/8] tree-object-size: Dynamic sizes for ADDR_EXPR Date: Fri, 26 Nov 2021 10:58:51 +0530 Message-Id: <20211126052851.2176408-9-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.8 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" Allow returning dynamic expressions from ADDR_EXPR for __builtin_dynamic_object_size and also allow offsets to be dynamic. gcc/ChangeLog: * tree-object-size.c (size_valid_p): New function. (size_for_offset): Remove OFFSET constness assertion. (addr_object_size): Build dynamic expressions for object sizes and use size_valid_p to decide if it is valid for the given OBJECT_SIZE_TYPE. (compute_builtin_object_size): Allow dynamic offsets when computing size at O0. (call_object_size): Call size_valid_p. (plus_stmt_object_size): Allow non-constant offset and use size_valid_p to decide if it is valid for the given OBJECT_SIZE_TYPE. 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]: Adjust expected output for dynamic object sizes. * 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 | 158 ++++++++++++++++++ gcc/testsuite/gcc.dg/builtin-object-size-1.c | 30 +++- gcc/testsuite/gcc.dg/builtin-object-size-2.c | 43 ++++- gcc/testsuite/gcc.dg/builtin-object-size-3.c | 25 ++- gcc/testsuite/gcc.dg/builtin-object-size-4.c | 17 +- gcc/tree-object-size.c | 91 +++++----- 6 files changed, 300 insertions(+), 64 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 2db0e0d1aa2..4a1f4965ebd 100644 --- a/gcc/testsuite/gcc.dg/builtin-dynamic-object-size-0.c +++ b/gcc/testsuite/gcc.dg/builtin-dynamic-object-size-0.c @@ -219,6 +219,79 @@ test_deploop (size_t sz, size_t cond) return __builtin_dynamic_object_size (bin, 0); } +/* Address expressions. */ + +struct dynarray_struct +{ + long a; + char c[16]; + int b; +}; + +size_t +__attribute__ ((noinline)) +test_dynarray_struct (size_t sz, size_t off) +{ + struct dynarray_struct bin[sz]; + + return __builtin_dynamic_object_size (&bin[off].c, 0); +} + +size_t +__attribute__ ((noinline)) +test_dynarray_struct_subobj (size_t sz, size_t off) +{ + struct dynarray_struct bin[sz]; + + return __builtin_dynamic_object_size (&bin[off].c[4], 1); +} + +size_t +__attribute__ ((noinline)) +test_dynarray_struct_subobj2 (size_t sz, size_t off, size_t *objsz) +{ + struct dynarray_struct2 + { + long a; + int b; + char c[sz]; + }; + + struct dynarray_struct2 bin; + + *objsz = sizeof (bin); + + return __builtin_dynamic_object_size (&bin.c[off], 1); +} + +size_t +__attribute__ ((noinline)) +test_substring (size_t sz, size_t off) +{ + char str[sz]; + + return __builtin_dynamic_object_size (&str[off], 0); +} + +size_t +__attribute__ ((noinline)) +test_substring_ptrplus (size_t sz, size_t off) +{ + int str[sz]; + + return __builtin_dynamic_object_size (str + off, 0); +} + +size_t +__attribute__ ((noinline)) +test_substring_ptrplus2 (size_t sz, size_t off, size_t off2) +{ + int str[sz]; + int *ptr = &str[off]; + + return __builtin_dynamic_object_size (ptr + off2, 0); +} + size_t __attribute__ ((access (__read_write__, 1, 2))) __attribute__ ((noinline)) @@ -227,6 +300,40 @@ test_parmsz_simple (void *obj, size_t sz) return __builtin_dynamic_object_size (obj, 0); } +size_t +__attribute__ ((noinline)) +__attribute__ ((access (__read_write__, 1, 2))) +test_parmsz (void *obj, size_t sz, size_t off) +{ + return __builtin_dynamic_object_size (obj + off, 0); +} + +size_t +__attribute__ ((noinline)) +__attribute__ ((access (__read_write__, 1, 2))) +test_parmsz_scale (int *obj, size_t sz, size_t off) +{ + return __builtin_dynamic_object_size (obj + off, 0); +} + +size_t +__attribute__ ((noinline)) +__attribute__ ((access (__read_write__, 1, 2))) +test_loop (int *obj, size_t sz, size_t start, size_t end, int incr) +{ + int *ptr = obj + start; + + for (int i = start; i != end; i = i + incr) + { + ptr = ptr + incr; + if (__builtin_dynamic_object_size (ptr, 0) == 0) + return 0; + } + + return __builtin_dynamic_object_size (ptr, 0); +} + + unsigned nfails = 0; #define FAIL() ({ \ @@ -287,6 +394,31 @@ main (int argc, char **argv) FAIL (); if (test_dynarray (__builtin_strlen (argv[0])) != __builtin_strlen (argv[0])) FAIL (); + if (test_dynarray_struct (42, 4) != + ((42 - 4) * sizeof (struct dynarray_struct) + - __builtin_offsetof (struct dynarray_struct, c))) + FAIL (); + if (test_dynarray_struct (42, 48) != 0) + FAIL (); + if (test_substring (128, 4) != 128 - 4) + FAIL (); + if (test_substring (128, 142) != 0) + FAIL (); + if (test_dynarray_struct_subobj (42, 4) != 16 - 4) + FAIL (); + if (test_dynarray_struct_subobj (42, 48) != 0) + FAIL (); + size_t objsz = 0; + if (test_dynarray_struct_subobj2 (42, 4, &objsz) != objsz - 4 - 12) + FAIL (); + if (test_substring_ptrplus (128, 4) != (128 - 4) * sizeof (int)) + FAIL (); + if (test_substring_ptrplus (128, 142) != 0) + FAIL (); + if (test_substring_ptrplus2 (128, 4, 4) != (128 - 8) * sizeof (int)) + FAIL (); + if (test_substring_ptrplus2 (128, 4, -3) != (128 - 1) * sizeof (int)) + FAIL (); if (test_dynarray_cond (0) != 16) FAIL (); if (test_dynarray_cond (1) != 8) @@ -298,6 +430,32 @@ main (int argc, char **argv) if (test_parmsz_simple (argv[0], __builtin_strlen (argv[0]) + 1) != __builtin_strlen (argv[0]) + 1) FAIL (); + if (test_parmsz (argv[0], __builtin_strlen (argv[0]) + 1, -1) != 0) + FAIL (); + if (test_parmsz (argv[0], __builtin_strlen (argv[0]) + 1, 0) + != __builtin_strlen (argv[0]) + 1) + FAIL (); + if (test_parmsz (argv[0], __builtin_strlen (argv[0]) + 1, + __builtin_strlen (argv[0])) != 1) + FAIL (); + if (test_parmsz (argv[0], __builtin_strlen (argv[0]) + 1, + __builtin_strlen (argv[0]) + 2) != 0) + FAIL (); + int in[42]; + if (test_parmsz_scale (in, 42, 2) != 40 * sizeof (int)) + FAIL (); + if (test_loop (in, 42, 0, 32, 1) != 10 * sizeof (int)) + FAIL (); + if (test_loop (in, 42, 32, -1, -1) != 0) + FAIL (); + if (test_loop (in, 42, 32, 10, -1) != 32 * sizeof (int)) + FAIL (); + if (test_loop (in, 42, 42, 0, -1) != 42 * sizeof (int)) + FAIL (); + if (test_loop (in, 42, 44, 0, -1) != 0) + FAIL (); + if (test_loop (in, 42, 20, 52, 1) != 0) + FAIL (); if (nfails > 0) __builtin_abort (); diff --git a/gcc/testsuite/gcc.dg/builtin-object-size-1.c b/gcc/testsuite/gcc.dg/builtin-object-size-1.c index 06d442796cb..161f426ec0b 100644 --- a/gcc/testsuite/gcc.dg/builtin-object-size-1.c +++ b/gcc/testsuite/gcc.dg/builtin-object-size-1.c @@ -81,30 +81,56 @@ test1 (void *q, int x) r = malloc (30); else r = calloc (2, 16); +#ifdef __builtin_object_size + if (__builtin_object_size (r, 0) != (x < 20 ? 30 : 2 * 16)) + abort (); +#else /* We may duplicate this test onto the two exit paths. On one path the size will be 32, the other it will be 30. If we don't duplicate this test, then the size will be 32. */ if (__builtin_object_size (r, 0) != 2 * 16 && __builtin_object_size (r, 0) != 30) abort (); +#endif if (x < 20) r = malloc (30); else r = calloc (2, 14); +#ifdef __builtin_object_size + if (__builtin_object_size (r, 0) != (x < 20 ? 30 : 2 * 14)) + abort (); +#else if (__builtin_object_size (r, 0) != 30) abort (); +#endif if (x < 30) r = malloc (sizeof (a)); else r = &a.a[3]; +#ifdef __builtin_object_size + if (__builtin_object_size (r, 0) != (x < 30 ? sizeof (a) : sizeof (a) - 3)) + abort (); +#else if (__builtin_object_size (r, 0) != sizeof (a)) abort (); +#endif r = memcpy (r, "a", 2); +#ifdef __builtin_object_size + if (__builtin_object_size (r, 0) != (x < 30 ? sizeof (a) : sizeof (a) - 3)) + abort (); +#else if (__builtin_object_size (r, 0) != sizeof (a)) abort (); +#endif r = memcpy (r + 2, "b", 2) + 2; +#ifdef __builtin_object_size + if (__builtin_object_size (r, 0) + != (x < 30 ? sizeof (a) - 4 : sizeof (a) - 7)) + abort (); +#else if (__builtin_object_size (r, 0) != sizeof (a) - 4) abort (); +#endif r = &a.a[4]; r = memset (r, 'a', 2); if (__builtin_object_size (r, 0) @@ -140,14 +166,16 @@ test1 (void *q, int x) abort (); if (__builtin_object_size (var + 10, 0) != x) abort (); + if (__builtin_object_size (&var[5], 0) != x + 5) + 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 (); +#endif if (__builtin_object_size (zerol, 0) != 0) 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 2364f2d6afd..2729538da17 100644 --- a/gcc/testsuite/gcc.dg/builtin-object-size-2.c +++ b/gcc/testsuite/gcc.dg/builtin-object-size-2.c @@ -75,30 +75,56 @@ test1 (void *q, int x) r = malloc (30); else r = calloc (2, 16); +#ifdef __builtin_object_size + if (__builtin_object_size (r, 1) != (x < 20 ? 30 : 2 * 16)) + abort (); +#else /* We may duplicate this test onto the two exit paths. On one path the size will be 32, the other it will be 30. If we don't duplicate this test, then the size will be 32. */ if (__builtin_object_size (r, 1) != 2 * 16 && __builtin_object_size (r, 1) != 30) abort (); +#endif if (x < 20) r = malloc (30); else r = calloc (2, 14); +#ifdef __builtin_object_size + if (__builtin_object_size (r, 1) != (x < 20 ? 30 : 2 * 14)) + abort (); +#else if (__builtin_object_size (r, 1) != 30) abort (); +#endif if (x < 30) r = malloc (sizeof (a)); else r = &a.a[3]; +#ifdef __builtin_object_size + if (__builtin_object_size (r, 1) != (x < 30 ? sizeof (a) : sizeof (a) - 3)) + abort (); +#else if (__builtin_object_size (r, 1) != sizeof (a)) abort (); +#endif r = memcpy (r, "a", 2); +#ifdef __builtin_object_size + if (__builtin_object_size (r, 1) != (x < 30 ? sizeof (a) : sizeof (a) - 3)) + abort (); +#else if (__builtin_object_size (r, 1) != sizeof (a)) abort (); +#endif r = memcpy (r + 2, "b", 2) + 2; +#ifdef __builtin_object_size + if (__builtin_object_size (r, 0) + != (x < 30 ? sizeof (a) - 4 : sizeof (a) - 7)) + abort (); +#else if (__builtin_object_size (r, 1) != sizeof (a) - 4) abort (); +#endif r = &a.a[4]; r = memset (r, 'a', 2); if (__builtin_object_size (r, 1) != sizeof (a.a) - 4) @@ -142,27 +168,28 @@ test1 (void *q, int x) abort (); if (__builtin_object_size (var + 10, 1) != x) abort (); + if (__builtin_object_size (&var[5], 1) != x + 5) + abort (); + if (__builtin_object_size (vara, 1) != (x + 10) * sizeof (struct A)) + abort (); + if (__builtin_object_size (vara + 10, 1) != x * sizeof (struct A)) + abort (); + if (__builtin_object_size (&vara[5], 1) != (x + 5) * sizeof (struct A)) + 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 (); +#endif if (__builtin_object_size (&vara[0].a, 1) != sizeof (vara[0].a)) abort (); if (__builtin_object_size (&vara[10].a[0], 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 753ee4a1a4f..db31171a8bd 100644 --- a/gcc/testsuite/gcc.dg/builtin-object-size-3.c +++ b/gcc/testsuite/gcc.dg/builtin-object-size-3.c @@ -42,9 +42,17 @@ test1 (void *q, int x) abort (); if (__builtin_object_size (q, 2) != 0) abort (); +#ifdef __builtin_object_size + if (__builtin_object_size (r, 2) + != (x < 0 + ? sizeof (a) - __builtin_offsetof (struct A, a) - 9 + : sizeof (a) - __builtin_offsetof (struct A, c) - 1)) + abort (); +#else if (__builtin_object_size (r, 2) != sizeof (a) - __builtin_offsetof (struct A, c) - 1) abort (); +#endif if (x < 6) r = &w[2].a[1]; else @@ -58,15 +66,28 @@ test1 (void *q, int x) if (__builtin_object_size (&y.b, 2) != sizeof (a) - __builtin_offsetof (struct A, b)) abort (); +#ifdef __builtin_object_size + if (__builtin_object_size (r, 2) + != (x < 6 + ? 2 * sizeof (w[0]) - __builtin_offsetof (struct A, a) - 1 + : sizeof (a) - __builtin_offsetof (struct A, a) - 6)) + abort (); +#else if (__builtin_object_size (r, 2) != sizeof (a) - __builtin_offsetof (struct A, a) - 6) abort (); +#endif if (x < 20) r = malloc (30); else r = calloc (2, 16); +#ifdef __builtin_object_size + if (__builtin_object_size (r, 2) != (x < 20 ? 30 : 2 * 16)) + abort (); +#else if (__builtin_object_size (r, 2) != 30) abort (); +#endif if (x < 20) r = malloc (30); else @@ -145,14 +166,16 @@ test1 (void *q, int x) abort (); if (__builtin_object_size (var + 10, 2) != x) abort (); + if (__builtin_object_size (&var[5], 2) != x + 5) + 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 (); +#endif if (__builtin_object_size (zerol, 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 c383385e060..f644890dd14 100644 --- a/gcc/testsuite/gcc.dg/builtin-object-size-4.c +++ b/gcc/testsuite/gcc.dg/builtin-object-size-4.c @@ -155,27 +155,28 @@ test1 (void *q, int x) abort (); if (__builtin_object_size (var + 10, 3) != x) abort (); + if (__builtin_object_size (&var[5], 3) != x + 5) + abort (); + if (__builtin_object_size (vara, 3) != (x + 10) * sizeof (struct A)) + abort (); + if (__builtin_object_size (vara + 10, 3) != x * sizeof (struct A)) + abort (); + if (__builtin_object_size (&vara[5], 3) != (x + 5) * sizeof (struct A)) + 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 (); +#endif if (__builtin_object_size (&vara[0].a, 3) != sizeof (vara[0].a)) abort (); if (__builtin_object_size (&vara[10].a[0], 3) != sizeof (vara[0].a)) diff --git a/gcc/tree-object-size.c b/gcc/tree-object-size.c index f03714c4f18..86cfb16855e 100644 --- a/gcc/tree-object-size.c +++ b/gcc/tree-object-size.c @@ -120,6 +120,14 @@ size_unknown_p (tree val, int object_size_type) && tree_to_uhwi (val) == unknown (object_size_type)); } +/* Return true if VAL is represents a valid size for OBJECT_SIZE_TYPE. */ + +static inline bool +size_valid_p (tree val, int object_size_type) +{ + return ((object_size_type & OST_DYNAMIC) || TREE_CODE (val) == INTEGER_CST); +} + /* Return a tree with initial value for OBJECT_SIZE_TYPE. */ static inline tree @@ -345,7 +353,6 @@ init_offset_limit (void) static tree size_for_offset (tree sz, tree offset, tree wholesize = NULL_TREE) { - gcc_checking_assert (TREE_CODE (offset) == INTEGER_CST); gcc_checking_assert (types_compatible_p (TREE_TYPE (sz), sizetype)); /* For negative offsets, if we have a distinct WHOLESIZE, use it to get a net @@ -544,18 +551,11 @@ addr_object_size (struct object_size_info *osi, const_tree ptr, sz = wholesize = size_unknown (object_size_type); } if (!size_unknown_p (sz, object_size_type)) - { - tree offset = TREE_OPERAND (pt_var, 1); - if (TREE_CODE (offset) != INTEGER_CST - || TREE_CODE (sz) != INTEGER_CST) - sz = wholesize = size_unknown (object_size_type); - else - sz = size_for_offset (sz, offset, wholesize); - } + sz = size_for_offset (sz, TREE_OPERAND (pt_var, 1), wholesize); if (!size_unknown_p (sz, object_size_type) - && TREE_CODE (sz) == INTEGER_CST - && compare_tree_int (sz, offset_limit) < 0) + && (TREE_CODE (sz) != INTEGER_CST + || compare_tree_int (sz, offset_limit) < 0)) { pt_var_size = sz; pt_var_wholesize = wholesize; @@ -575,8 +575,9 @@ addr_object_size (struct object_size_info *osi, const_tree ptr, if (pt_var_size) { - /* Validate the size determined above. */ - if (compare_tree_int (pt_var_size, offset_limit) >= 0) + /* Validate the size determined above if it is a constant. */ + if (TREE_CODE (pt_var_size) == INTEGER_CST + && compare_tree_int (pt_var_size, offset_limit) >= 0) return false; } @@ -600,7 +601,7 @@ addr_object_size (struct object_size_info *osi, const_tree ptr, var = TREE_OPERAND (var, 0); if (! TYPE_SIZE_UNIT (TREE_TYPE (var)) || ! tree_fits_uhwi_p (TYPE_SIZE_UNIT (TREE_TYPE (var))) - || (pt_var_size + || (pt_var_size && TREE_CODE (pt_var_size) == INTEGER_CST && tree_int_cst_lt (pt_var_size, TYPE_SIZE_UNIT (TREE_TYPE (var))))) var = pt_var; @@ -614,17 +615,11 @@ addr_object_size (struct object_size_info *osi, const_tree ptr, switch (TREE_CODE (v)) { case ARRAY_REF: - if (TYPE_SIZE_UNIT (TREE_TYPE (TREE_OPERAND (v, 0))) - && TREE_CODE (TREE_OPERAND (v, 1)) == INTEGER_CST) + if (TYPE_SIZE_UNIT (TREE_TYPE (TREE_OPERAND (v, 0)))) { tree domain = TYPE_DOMAIN (TREE_TYPE (TREE_OPERAND (v, 0))); - if (domain - && TYPE_MAX_VALUE (domain) - && TREE_CODE (TYPE_MAX_VALUE (domain)) - == INTEGER_CST - && tree_int_cst_lt (TREE_OPERAND (v, 1), - TYPE_MAX_VALUE (domain))) + if (domain && TYPE_MAX_VALUE (domain)) { v = NULL_TREE; break; @@ -691,20 +686,20 @@ addr_object_size (struct object_size_info *osi, const_tree ptr, var = pt_var; if (var != pt_var) - var_size = TYPE_SIZE_UNIT (TREE_TYPE (var)); + { + var_size = TYPE_SIZE_UNIT (TREE_TYPE (var)); + if (!TREE_CONSTANT (var_size)) + var_size = get_or_create_ssa_default_def (cfun, var_size); + if (!var_size) + return false; + } else if (!pt_var_size) return false; else var_size = pt_var_size; bytes = compute_object_offset (TREE_OPERAND (ptr, 0), var); if (bytes != error_mark_node) - { - if (TREE_CODE (bytes) == INTEGER_CST - && tree_int_cst_lt (var_size, bytes)) - bytes = size_zero_node; - else - bytes = size_binop (MINUS_EXPR, var_size, bytes); - } + bytes = size_for_offset (var_size, bytes); if (var != pt_var && pt_var_size && TREE_CODE (pt_var) == MEM_REF @@ -713,11 +708,7 @@ addr_object_size (struct object_size_info *osi, const_tree ptr, tree bytes2 = compute_object_offset (TREE_OPERAND (ptr, 0), pt_var); if (bytes2 != error_mark_node) { - if (TREE_CODE (bytes2) == INTEGER_CST - && tree_int_cst_lt (pt_var_size, bytes2)) - bytes2 = size_zero_node; - else - bytes2 = size_binop (MINUS_EXPR, pt_var_size, bytes2); + bytes2 = size_for_offset (pt_var_size, bytes2); bytes = size_binop (MIN_EXPR, bytes, bytes2); } } @@ -733,14 +724,18 @@ addr_object_size (struct object_size_info *osi, const_tree ptr, wholebytes = pt_var_wholesize; } - if (TREE_CODE (bytes) != INTEGER_CST - || TREE_CODE (wholebytes) != INTEGER_CST) - return false; + if (!size_unknown_p (bytes, object_size_type) + && size_valid_p (bytes, object_size_type) + && !size_unknown_p (bytes, object_size_type) + && size_valid_p (wholebytes, object_size_type)) + { + *psize = bytes; + if (pwholesize) + *pwholesize = wholebytes; + return true; + } - *psize = bytes; - if (pwholesize) - *pwholesize = wholebytes; - return true; + return false; } @@ -1066,11 +1061,11 @@ compute_builtin_object_size (tree ptr, int object_size_type, tree offset = gimple_assign_rhs2 (def); ptr = gimple_assign_rhs1 (def); - if (tree_fits_shwi_p (offset) + if (((object_size_type & OST_DYNAMIC) + || tree_fits_shwi_p (offset)) && compute_builtin_object_size (ptr, object_size_type, psize)) { - /* Return zero when the offset is out of bounds. */ *psize = size_for_offset (*psize, offset); return true; } @@ -1255,7 +1250,7 @@ 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) + if (!size_valid_p (bytes, object_size_type)) bytes = size_unknown (object_size_type); object_sizes_set (osi, varno, bytes, bytes); @@ -1335,7 +1330,7 @@ plus_stmt_object_size (struct object_size_info *osi, tree var, gimple *stmt) return false; /* Handle PTR + OFFSET here. */ - if (TREE_CODE (op1) == INTEGER_CST + if (((object_size_type & OST_DYNAMIC) || TREE_CODE (op1) == INTEGER_CST) && (TREE_CODE (op0) == SSA_NAME || TREE_CODE (op0) == ADDR_EXPR)) { @@ -1368,6 +1363,10 @@ plus_stmt_object_size (struct object_size_info *osi, tree var, gimple *stmt) else bytes = wholesize = size_unknown (object_size_type); + if (!size_valid_p (bytes, object_size_type) + || !size_valid_p (wholesize, object_size_type)) + bytes = wholesize = size_unknown (object_size_type); + osi->changed = object_sizes_set (osi, varno, bytes, wholesize); return reexamine; }