From patchwork Thu Jun 14 19:04:10 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Luc Van Oostenryck X-Patchwork-Id: 10465031 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 31BBE60532 for ; Thu, 14 Jun 2018 19:04:39 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 20DED28BE9 for ; Thu, 14 Jun 2018 19:04:39 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 15C0428C0C; Thu, 14 Jun 2018 19:04:39 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.8 required=2.0 tests=BAYES_00, DKIM_ADSP_CUSTOM_MED, DKIM_SIGNED, FREEMAIL_FROM, MAILING_LIST_MULTI, RCVD_IN_DNSWL_HI, T_DKIM_INVALID autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 352BB28C0E for ; Thu, 14 Jun 2018 19:04:38 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1755392AbeFNTEh (ORCPT ); Thu, 14 Jun 2018 15:04:37 -0400 Received: from mail-wm0-f67.google.com ([74.125.82.67]:33445 "EHLO mail-wm0-f67.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1754780AbeFNTEg (ORCPT ); Thu, 14 Jun 2018 15:04:36 -0400 Received: by mail-wm0-f67.google.com with SMTP id z6-v6so4198376wma.0 for ; Thu, 14 Jun 2018 12:04:36 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=smkHO24Qvh2C9P7TmkEBSPoC+t9Ryu3kCcf05486LaU=; b=HKtRmxbT4o9ucKhdTMXU/6BNwYRXuvaiH1DAm9NJz1T8vyce8lSe/QhcH760ChfZL2 U28Iv8YWP4yqrDE0df0FhNdIdAHTIHGPoGRsboxyNXdZOgakGOFNyLa2YTGWvZgTzR45 /aKMBj6JIBq7TnIlFXsD1Aonpd7i8x7zeuIKIvr08Pn443pU59c5KYuZ+jX+vk3gEk4B MaL5cvR4et5cu31gogw9+KND7o04VMV9f1w4tiY34U05YVrFY8ExasJ6sxxWQqPhluQB iyId46HczLY61sgwHDa3paifDZwLP4T1EIzV0jDEi8mbWI3zslVeT+pgjEwY8YgHamNK YSXA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=smkHO24Qvh2C9P7TmkEBSPoC+t9Ryu3kCcf05486LaU=; b=RJ731rjy5y30mcJ3pooFEcPx4q/XYVjCI9Ayf8pHqjiaPRii3ZDFVsBbK2wNgNESX4 SbEO3sN2Z0DSMPaoMg2xxgrOs3s2ba83rLcnyRXGFYsIJw4uSq13CbOXD4Ue8vE+QS7o gmJUDxemDgXf1+1dURrhdhrtWl7JxthdjQbltRNIXupCfRwei/n5H9m+J0Qw5kkqcQZD 1ThSFjnphz2px7CidJEJz6URPNBvOVIrAW0qaxwu/VCXpI6Gqq/yWdy5m50zuSu1Iq+X Wj08HWNr3h6KLbUlNfofiVJEF1lUd26Eg2Bq5vbc2RXL6Ascq1ZeYdzL2TKo5DZgjfNn P8RQ== X-Gm-Message-State: APt69E06C+parEJXnOu+ECfEPOIh+AozHXu+SrznTKLY5ej5l7h8ur3O ug31acvkyrwnhXUw1rHUzdO8CUu++ak= X-Google-Smtp-Source: ADUXVKIe26Qgp1MOhJ54wsI66FbPw+duywYaY/aYcU7tS9kbLPAUtJPDHOzctn/OX5CWwsYXWxW5EQ== X-Received: by 2002:a50:a106:: with SMTP id 6-v6mr3675751edj.12.1529003075106; Thu, 14 Jun 2018 12:04:35 -0700 (PDT) Received: from localhost.localdomain ([2a02:a03f:4033:b700:7008:9bbf:83ef:4c95]) by smtp.gmail.com with ESMTPSA id m42-v6sm3303524edc.94.2018.06.14.12.04.34 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 14 Jun 2018 12:04:34 -0700 (PDT) From: Luc Van Oostenryck To: linux-sparse@vger.kernel.org Cc: Luc Van Oostenryck Subject: [PATCH 11/20] cast: specialize casts from unsigned to pointers Date: Thu, 14 Jun 2018 21:04:10 +0200 Message-Id: <20180614190419.28052-12-luc.vanoostenryck@gmail.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20180614190419.28052-1-luc.vanoostenryck@gmail.com> References: <20180614190419.28052-1-luc.vanoostenryck@gmail.com> Sender: linux-sparse-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-sparse@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Currently all casts to pointers are processed alike. This is simple but rather unconvenient as it correspond to different operations that obeys to different rules and which later need extra checks. Change this by using a specific instructions (OP_UTPTR) for unsigned integer to pointers. Signed-off-by: Luc Van Oostenryck --- Documentation/IR.rst | 3 ++ cse.c | 2 ++ example.c | 2 ++ lib.c | 2 ++ lib.h | 1 + linearize.c | 22 +++++++++++++- linearize.h | 1 + liveness.c | 1 + simplify.c | 3 ++ sparse-llvm.c | 1 + validation/backend/pointer-sub.c | 2 +- validation/cast-kinds-check.c | 2 ++ validation/cast-weirds.c | 49 ++++++++++++++++++++++++++++++++ validation/linear/cast-kinds.c | 10 +++---- validation/optim/kill-casts.c | 1 + 15 files changed, 95 insertions(+), 7 deletions(-) create mode 100644 validation/cast-weirds.c diff --git a/Documentation/IR.rst b/Documentation/IR.rst index 5b9155f76..56f023183 100644 --- a/Documentation/IR.rst +++ b/Documentation/IR.rst @@ -270,6 +270,9 @@ They all have the following signature: .. op:: OP_SCAST Cast to signed integer. +.. op:: OP_UTPTR + Cast from unsigned integer to pointer type. + .. op:: OP_PTRCAST Cast to pointer. diff --git a/cse.c b/cse.c index 79d37cfd1..2a0767093 100644 --- a/cse.c +++ b/cse.c @@ -94,6 +94,7 @@ void cse_collect(struct instruction *insn) case OP_CAST: case OP_SCAST: case OP_PTRCAST: + case OP_UTPTR: /* * This is crap! Many "orig_types" are the * same as far as casts go, we should generate @@ -241,6 +242,7 @@ static int insn_compare(const void *_i1, const void *_i2) case OP_CAST: case OP_SCAST: case OP_PTRCAST: + case OP_UTPTR: /* * This is crap! See the comments on hashing. */ diff --git a/example.c b/example.c index 89ef7b834..20c950483 100644 --- a/example.c +++ b/example.c @@ -81,6 +81,7 @@ static const char *opcodes[] = { [OP_UCVTF] = "ucvtf", [OP_SCVTF] = "scvtf", [OP_FCVTF] = "fcvtf", + [OP_UTPTR] = "utptr", [OP_PTRCAST] = "ptrcast", [OP_CALL] = "call", [OP_SLICE] = "slice", @@ -1414,6 +1415,7 @@ static void generate_one_insn(struct instruction *insn, struct bb_state *state) break; case OP_CAST: case OP_SCAST: case OP_PTRCAST: + case OP_UTPTR: case OP_FCVTU: case OP_FCVTS: case OP_UCVTF: case OP_SCVTF: case OP_FCVTF: diff --git a/lib.c b/lib.c index d549c554e..dd7374b53 100644 --- a/lib.c +++ b/lib.c @@ -257,6 +257,7 @@ int Wdefault_bitfield_sign = 0; int Wdesignated_init = 1; int Wdo_while = 0; int Winit_cstring = 0; +int Wint_to_pointer_cast = 1; int Wenum_mismatch = 1; int Wsparse_error = 0; int Wmemcpy_max_count = 1; @@ -685,6 +686,7 @@ static const struct flag warnings[] = { { "do-while", &Wdo_while }, { "enum-mismatch", &Wenum_mismatch }, { "init-cstring", &Winit_cstring }, + { "int-to-pointer-cast", &Wint_to_pointer_cast }, { "memcpy-max-count", &Wmemcpy_max_count }, { "non-pointer-null", &Wnon_pointer_null }, { "old-initializer", &Wold_initializer }, diff --git a/lib.h b/lib.h index c9a55b60d..afa02ec18 100644 --- a/lib.h +++ b/lib.h @@ -149,6 +149,7 @@ extern int Wdo_while; extern int Wenum_mismatch; extern int Wsparse_error; extern int Winit_cstring; +extern int Wint_to_pointer_cast; extern int Wmemcpy_max_count; extern int Wnon_pointer_null; extern int Wold_initializer; diff --git a/linearize.c b/linearize.c index a05589367..29efc67a9 100644 --- a/linearize.c +++ b/linearize.c @@ -268,6 +268,7 @@ static const char *opcodes[] = { [OP_UCVTF] = "ucvtf", [OP_SCVTF] = "scvtf", [OP_FCVTF] = "fcvtf", + [OP_UTPTR] = "utptr", [OP_PTRCAST] = "ptrcast", [OP_INLINED_CALL] = "# call", [OP_CALL] = "call", @@ -452,6 +453,7 @@ const char *show_instruction(struct instruction *insn) case OP_FCVTU: case OP_FCVTS: case OP_UCVTF: case OP_SCVTF: case OP_FCVTF: + case OP_UTPTR: case OP_PTRCAST: buf += sprintf(buf, "%s <- (%d) %s", show_pseudo(insn->target), @@ -1220,7 +1222,17 @@ static int get_cast_opcode(struct symbol *dst, struct symbol *src) return OP_BADOP; } case MTYPE_PTR: - return OP_PTRCAST; + switch (stype) { + case MTYPE_UINT: + case MTYPE_SINT: + if (is_ptr_type(src)) // must be a void pointer + return OP_PTRCAST;// FIXME: to be removed? + return OP_UTPTR; + case MTYPE_PTR: + return OP_PTRCAST; + default: + return OP_BADOP; + } case MTYPE_UINT: case MTYPE_SINT: switch (stype) { @@ -1253,6 +1265,14 @@ static pseudo_t cast_pseudo(struct entrypoint *ep, pseudo_t src, struct symbol * switch (opcode) { case OP_NOP: return src; + case OP_UTPTR: + if (from->bit_size == to->bit_size) + break; + if (src == value_pseudo(0)) + break; + if (Wint_to_pointer_cast) + warning(to->pos, "non size-preserving integer to pointer cast"); + break; default: break; } diff --git a/linearize.h b/linearize.h index 8b1cb7950..20ede605c 100644 --- a/linearize.h +++ b/linearize.h @@ -237,6 +237,7 @@ enum opcode { OP_FCVTU, OP_FCVTS, OP_UCVTF, OP_SCVTF, OP_FCVTF, + OP_UTPTR, OP_PTRCAST, OP_INLINED_CALL, OP_CALL, diff --git a/liveness.c b/liveness.c index bf5c9a692..af71f146b 100644 --- a/liveness.c +++ b/liveness.c @@ -116,6 +116,7 @@ static void track_instruction_usage(struct basic_block *bb, struct instruction * case OP_FCVTU: case OP_FCVTS: case OP_UCVTF: case OP_SCVTF: case OP_FCVTF: + case OP_UTPTR: case OP_PTRCAST: USES(src); DEFINES(target); break; diff --git a/simplify.c b/simplify.c index 642198ab1..03b9d244a 100644 --- a/simplify.c +++ b/simplify.c @@ -256,6 +256,7 @@ int kill_insn(struct instruction *insn, int force) case OP_FCVTU: case OP_FCVTS: case OP_UCVTF: case OP_SCVTF: case OP_FCVTF: + case OP_UTPTR: case OP_PTRCAST: case OP_SETVAL: case OP_NOT: case OP_NEG: @@ -359,6 +360,7 @@ static int replace_with_pseudo(struct instruction *insn, pseudo_t pseudo) case OP_FCVTU: case OP_FCVTS: case OP_UCVTF: case OP_SCVTF: case OP_FCVTF: + case OP_UTPTR: case OP_PTRCAST: kill_use(&insn->src1); break; @@ -1230,6 +1232,7 @@ int simplify_instruction(struct instruction *insn) case OP_FCVTU: case OP_FCVTS: case OP_UCVTF: case OP_SCVTF: case OP_FCVTF: + case OP_UTPTR: case OP_PTRCAST: return simplify_cast(insn); case OP_PHI: diff --git a/sparse-llvm.c b/sparse-llvm.c index 29362f892..cddabba0d 100644 --- a/sparse-llvm.c +++ b/sparse-llvm.c @@ -1045,6 +1045,7 @@ static void output_insn(struct function *fn, struct instruction *insn) case OP_FCVTF: output_op_fpcast(fn, insn); break; + case OP_UTPTR: case OP_PTRCAST: output_op_ptrcast(fn, insn); break; diff --git a/validation/backend/pointer-sub.c b/validation/backend/pointer-sub.c index 3cb8f5a9d..5c99f4faf 100644 --- a/validation/backend/pointer-sub.c +++ b/validation/backend/pointer-sub.c @@ -13,5 +13,5 @@ long subvx3(void *p, int a) { return (p - ((void*)0)) ^ 3; } /* * check-name: pointer-sub - * check-command: sparsec -Wno-decl -c $file -o tmp.o + * check-command: sparsec -Wno-int-to-pointer-cast -Wno-decl -c $file -o tmp.o */ diff --git a/validation/cast-kinds-check.c b/validation/cast-kinds-check.c index 1f10e0ecf..736ab3910 100644 --- a/validation/cast-kinds-check.c +++ b/validation/cast-kinds-check.c @@ -20,5 +20,7 @@ linear/cast-kinds.c:29:51: warning: cast wasn't removed linear/cast-kinds.c:34:52: warning: cast wasn't removed linear/cast-kinds.c:35:54: warning: cast wasn't removed linear/cast-kinds.c:36:52: warning: cast wasn't removed +linear/cast-kinds.c:37:42: warning: non size-preserving integer to pointer cast +linear/cast-kinds.c:38:44: warning: non size-preserving integer to pointer cast * check-error-end */ diff --git a/validation/cast-weirds.c b/validation/cast-weirds.c new file mode 100644 index 000000000..136137b4c --- /dev/null +++ b/validation/cast-weirds.c @@ -0,0 +1,49 @@ +typedef unsigned int uint; +typedef unsigned long ulong; + +static int * int_2_iptr(int a) { return (int *)a; } +static int * uint_2_iptr(uint a) { return (int *)a; } + +static void * int_2_vptr(int a) { return (void *)a; } +static void * uint_2_vptr(uint a) { return (void *)a; } + +/* + * check-name: cast-weirds + * check-command: test-linearize -m64 $file + * + * check-error-start +cast-weirds.c:4:42: warning: non size-preserving integer to pointer cast +cast-weirds.c:5:44: warning: non size-preserving integer to pointer cast + * check-error-end + * + * check-output-start +int_2_iptr: +.L0: + + utptr.64 %r2 <- (32) %arg1 + ret.64 %r2 + + +uint_2_iptr: +.L2: + + utptr.64 %r5 <- (32) %arg1 + ret.64 %r5 + + +int_2_vptr: +.L4: + + scast.64 %r8 <- (32) %arg1 + ret.64 %r8 + + +uint_2_vptr: +.L6: + + cast.64 %r11 <- (32) %arg1 + ret.64 %r11 + + + * check-output-end + */ diff --git a/validation/linear/cast-kinds.c b/validation/linear/cast-kinds.c index d07a94190..4449d0af8 100644 --- a/validation/linear/cast-kinds.c +++ b/validation/linear/cast-kinds.c @@ -55,7 +55,7 @@ static double double_2_double(double a) { return a; } /* * check-name: cast-kinds - * check-command: test-linearize -m64 $file + * check-command: test-linearize -Wno-int-to-pointer-cast -m64 $file * * check-output-start uint_2_int: @@ -288,28 +288,28 @@ iptr_2_vptr: int_2_iptr: .L66: - ptrcast.64 %r101 <- (32) %arg1 + utptr.64 %r101 <- (32) %arg1 ret.64 %r101 uint_2_iptr: .L68: - ptrcast.64 %r104 <- (32) %arg1 + utptr.64 %r104 <- (32) %arg1 ret.64 %r104 long_2_iptr: .L70: - ptrcast.64 %r107 <- (64) %arg1 + utptr.64 %r107 <- (64) %arg1 ret.64 %r107 ulong_2_iptr: .L72: - ptrcast.64 %r110 <- (64) %arg1 + utptr.64 %r110 <- (64) %arg1 ret.64 %r110 diff --git a/validation/optim/kill-casts.c b/validation/optim/kill-casts.c index b79335abb..c375f5fbc 100644 --- a/validation/optim/kill-casts.c +++ b/validation/optim/kill-casts.c @@ -20,4 +20,5 @@ void foo(struct s *x) * check-output-ignore * check-output-excludes: cast\\. * check-output-excludes: fcvt[us]\\. + * check-output-excludes: utptr\\. */