From patchwork Mon Jan 24 09:00:49 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jakub Jelinek X-Patchwork-Id: 50381 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 D24AB3858405 for ; Mon, 24 Jan 2022 09:01:45 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org D24AB3858405 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1643014905; bh=S4R1gZDDNMj5HtbF2Hej8ZQ1hajAakMrkvSrQFGwMo8=; h=Date:To:Subject:References:In-Reply-To:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To:Cc: From; b=CRk/D1PfnKeS024oGootFfks9Us3pIvxsn9GHJ+2eQXNuGoppmcSQUMoZiKvnZnZD E1oJ7nnALI9VLOeoLrxuks1H5x5gLsgydLPvF++TWctxaM64oBXWh/iBAnvuuGbQan dcdGgEE7CuPX2XgHtn5GDkKqL6R+nDqAUEJv3Aps= X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) by sourceware.org (Postfix) with ESMTPS id 36E153858D3C for ; Mon, 24 Jan 2022 09:01:16 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 36E153858D3C Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-617-HtpXoCAtPKieKeo4VzMYDQ-1; Mon, 24 Jan 2022 04:00:56 -0500 X-MC-Unique: HtpXoCAtPKieKeo4VzMYDQ-1 Received: from smtp.corp.redhat.com (int-mx08.intmail.prod.int.phx2.redhat.com [10.5.11.23]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 131B584BA44; Mon, 24 Jan 2022 09:00:55 +0000 (UTC) Received: from tucnak.zalov.cz (unknown [10.39.192.125]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 8B5EC16A5F; Mon, 24 Jan 2022 09:00:54 +0000 (UTC) Received: from tucnak.zalov.cz (localhost [127.0.0.1]) by tucnak.zalov.cz (8.16.1/8.16.1) with ESMTPS id 20O90psD3702772 (version=TLSv1.3 cipher=TLS_AES_256_GCM_SHA384 bits=256 verify=NOT); Mon, 24 Jan 2022 10:00:51 +0100 Received: (from jakub@localhost) by tucnak.zalov.cz (8.16.1/8.16.1/Submit) id 20O90npC3702771; Mon, 24 Jan 2022 10:00:49 +0100 Date: Mon, 24 Jan 2022 10:00:49 +0100 To: "Joseph S. Myers" Subject: [PATCH] options: Add EnumBitSet property support [PR104158] Message-ID: <20220124090049.GI2646553@tucnak> References: <20220122004708.GO2646553@tucnak> MIME-Version: 1.0 In-Reply-To: <20220122004708.GO2646553@tucnak> X-Scanned-By: MIMEDefang 2.84 on 10.5.11.23 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Disposition: inline X-Spam-Status: No, score=-5.2 required=5.0 tests=BAYES_00, DKIMWL_WL_HIGH, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, RCVD_IN_DNSWL_LOW, RCVD_IN_MSPIKE_H3, RCVD_IN_MSPIKE_WL, SPF_HELO_NONE, SPF_NONE, 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: , X-Patchwork-Original-From: Jakub Jelinek via Gcc-patches From: Jakub Jelinek Reply-To: Jakub Jelinek Cc: Marek Polacek , gcc-patches@gcc.gnu.org Errors-To: gcc-patches-bounces+patchwork=sourceware.org@gcc.gnu.org Sender: "Gcc-patches" On Sat, Jan 22, 2022 at 01:47:08AM +0100, Jakub Jelinek via Gcc-patches wrote: > I think with the 2) patch I achieve what we want for Fortran, for 1) > the only behavior from gcc 11 is that > -fsanitize-coverage=trace-cmp,trace-cmp is now rejected. > This is mainly from the desire to disallow > -fconvert=big-endian,little-endian or -Wbidi-chars=bidirectional,any > etc. where it would be confusing to users what exactly it means. > But it is the only from these options that actually acts as an Enum > bit set, each enumerator can be specified with all the others. > So one option would be stop requiring the EnumSet implies Set properties > must be specified and just require that either they are specified on all > EnumValues, or on none of them; the latter case would be for > -fsanitize-coverage= and the non-Set case would mean that all the > EnumValues need to have disjoint Value bitmasks and that they can > be all specified and unlike the Set case also repeated. > Thoughts on this? Here is an incremental patch to the first two patches of the series that implements EnumBitSet that fully restores the -fsanitize-coverage GCC 11 behavior. Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk? 2022-01-24 Jakub Jelinek PR sanitizer/104158 * opt-functions.awk (var_set): Handle EnumBitSet property. * optc-gen.awk: Don't disallow RejectNegative if EnumBitSet is specified. * opts.h (enum cl_enum_var_value): New type. * opts-common.cc (decode_cmdline_option): Use CLEV_* values. Handle CLEV_BITSET. (cmdline_handle_error): Handle CLEV_BITSET. * opts.cc (test_enum_sets): Also test EnumBitSet requirements. * doc/options.texi (EnumBitSet): Document. * common.opt (fsanitize-coverage=): Use EnumBitSet instead of EnumSet. (trace-pc, trace-cmp): Drop Set properties. * gcc.dg/sancov/pr104158-7.c: Adjust for repeating of arguments being allowed. Jakub --- gcc/opt-functions.awk.jj 2022-01-23 17:25:21.166588518 +0100 +++ gcc/opt-functions.awk 2022-01-23 17:30:17.989443241 +0100 @@ -298,9 +298,11 @@ function var_set(flags) if (flag_set_p("Enum.*", flags)) { en = opt_args("Enum", flags); if (flag_set_p("EnumSet", flags)) - return enum_index[en] ", CLVC_ENUM, 1" + return enum_index[en] ", CLVC_ENUM, CLEV_SET" + else if (flag_set_p("EnumBitSet", flags)) + return enum_index[en] ", CLVC_ENUM, CLEV_BITSET" else - return enum_index[en] ", CLVC_ENUM, 0" + return enum_index[en] ", CLVC_ENUM, CLEV_NORMAL" } if (var_type(flags) == "const char *") return "0, CLVC_STRING, 0" --- gcc/optc-gen.awk.jj 2022-01-23 17:25:21.000000000 +0100 +++ gcc/optc-gen.awk 2022-01-23 17:26:38.920502407 +0100 @@ -349,6 +349,7 @@ for (i = 0; i < n_opts; i++) { if (flag_set_p("Enum.*", flags[i])) { if (!flag_set_p("RejectNegative", flags[i]) \ && !flag_set_p("EnumSet", flags[i]) \ + && !flag_set_p("EnumBitSet", flags[i]) \ && opts[i] ~ "^[Wfgm]") print "#error Enum allowing negative form" } --- gcc/opts.h.jj 2022-01-23 17:25:21.167588504 +0100 +++ gcc/opts.h 2022-01-23 17:30:00.469687787 +0100 @@ -52,6 +52,18 @@ enum cl_var_type { CLVC_DEFER }; +/* Values for var_value member of CLVC_ENUM. */ +enum cl_enum_var_value { + /* Enum without EnumSet or EnumBitSet. */ + CLEV_NORMAL, + + /* EnumSet. */ + CLEV_SET, + + /* EnumBitSet. */ + CLEV_BITSET +}; + struct cl_option { /* Text of the option, including initial '-'. */ --- gcc/opts-common.cc.jj 2022-01-23 17:25:21.169588477 +0100 +++ gcc/opts-common.cc 2022-01-23 17:38:00.508987332 +0100 @@ -811,8 +811,8 @@ decode_cmdline_option (const char *const { const struct cl_enum *e = &cl_enums[option->var_enum]; - gcc_assert (option->var_value || value == 1); - if (option->var_value) + gcc_assert (option->var_value != CLEV_NORMAL || value == 1); + if (option->var_value != CLEV_NORMAL) { const char *p = arg; HOST_WIDE_INT sum_value = 0; @@ -834,19 +834,30 @@ decode_cmdline_option (const char *const break; } - unsigned set = e->values[idx].flags >> CL_ENUM_SET_SHIFT; - gcc_checking_assert (set >= 1 && set <= HOST_BITS_PER_WIDE_INT); - if ((used_sets & (HOST_WIDE_INT_1U << (set - 1))) != 0) + HOST_WIDE_INT this_mask = 0; + if (option->var_value == CLEV_SET) { - errors |= CL_ERR_ENUM_SET_ARG; - break; + unsigned set = e->values[idx].flags >> CL_ENUM_SET_SHIFT; + gcc_checking_assert (set >= 1 + && set <= HOST_BITS_PER_WIDE_INT); + if ((used_sets & (HOST_WIDE_INT_1U << (set - 1))) != 0) + { + errors |= CL_ERR_ENUM_SET_ARG; + break; + } + used_sets |= HOST_WIDE_INT_1U << (set - 1); + + for (int i = 0; e->values[i].arg != NULL; i++) + if (set == (e->values[i].flags >> CL_ENUM_SET_SHIFT)) + this_mask |= e->values[i].value; + } + else + { + gcc_assert (option->var_value == CLEV_BITSET + && ((e->values[idx].flags >> CL_ENUM_SET_SHIFT) + == 0)); + this_mask = this_value; } - used_sets |= HOST_WIDE_INT_1U << (set - 1); - - HOST_WIDE_INT this_mask = 0; - for (int i = 0; e->values[i].arg != NULL; i++) - if (set == (e->values[i].flags >> CL_ENUM_SET_SHIFT)) - this_mask |= e->values[i].value; sum_value |= this_value; mask |= this_mask; @@ -1430,6 +1441,14 @@ cmdline_handle_error (location_t loc, co break; } + if (option->var_value == CLEV_BITSET) + { + if (q == NULL) + break; + p = q + 1; + continue; + } + unsigned set = e->values[idx].flags >> CL_ENUM_SET_SHIFT; gcc_checking_assert (set >= 1 && set <= HOST_BITS_PER_WIDE_INT); if ((used_sets & (HOST_WIDE_INT_1U << (set - 1))) != 0) --- gcc/opts.cc.jj 2022-01-23 17:25:25.554527225 +0100 +++ gcc/opts.cc 2022-01-23 17:48:55.505842425 +0100 @@ -3705,13 +3705,14 @@ test_get_option_html_page () #endif } -/* Verify EnumSet requirements. */ +/* Verify EnumSet and EnumBitSet requirements. */ static void test_enum_sets () { for (unsigned i = 0; i < cl_options_count; ++i) - if (cl_options[i].var_type == CLVC_ENUM && cl_options[i].var_value) + if (cl_options[i].var_type == CLVC_ENUM + && cl_options[i].var_value != CLEV_NORMAL) { const struct cl_enum *e = &cl_enums[cl_options[i].var_enum]; unsigned HOST_WIDE_INT used_sets = 0; @@ -3720,12 +3721,22 @@ test_enum_sets () for (unsigned j = 0; e->values[j].arg; ++j) { unsigned set = e->values[j].flags >> CL_ENUM_SET_SHIFT; + if (cl_options[i].var_value == CLEV_BITSET) + { + /* For EnumBitSet Set shouldn't be used and Value should + be a power of two. */ + ASSERT_TRUE (set == 0); + ASSERT_TRUE (pow2p_hwi (e->values[j].value)); + continue; + } /* Test that enumerators referenced in EnumSet have all Set(n) on them within the valid range. */ ASSERT_TRUE (set >= 1 && set <= HOST_BITS_PER_WIDE_INT); highest_set = MAX (set, highest_set); used_sets |= HOST_WIDE_INT_1U << (set - 1); } + if (cl_options[i].var_value == CLEV_BITSET) + continue; /* If there is just one set, no point to using EnumSet. */ ASSERT_TRUE (highest_set >= 2); /* Test that there are no gaps in between the sets. */ --- gcc/doc/options.texi.jj 2022-01-23 17:25:21.169588477 +0100 +++ gcc/doc/options.texi 2022-01-23 17:52:19.005999122 +0100 @@ -421,6 +421,14 @@ enumeration values with the same set bit Or option's argument can be a comma separated list of strings where each string is from a different @code{Set(@var{number})}. +@item EnumBitSet +Must be used together with the @code{Enum(@var{name})} property. +Similar to @samp{EnumBitSet}, but corresponding @samp{Enum} record must +not use @code{Set} properties, each @code{EnumValue} should have +@code{Value} that is a power of 2, each value is treated as its own +set and its value as the set's mask, so there are no mutually +exclusive arguments. + @item Defer The option should be stored in a vector, specified with @code{Var}, for later processing. --- gcc/common.opt.jj 2022-01-23 17:25:25.553527239 +0100 +++ gcc/common.opt 2022-01-23 17:26:11.640883463 +0100 @@ -1072,17 +1072,17 @@ Common Driver Joined Select what to sanitize. fsanitize-coverage= -Common Joined Enum(sanitize_coverage) Var(flag_sanitize_coverage) EnumSet +Common Joined Enum(sanitize_coverage) Var(flag_sanitize_coverage) EnumBitSet Select type of coverage sanitization. Enum Name(sanitize_coverage) Type(int) EnumValue -Enum(sanitize_coverage) String(trace-pc) Value(SANITIZE_COV_TRACE_PC) Set(1) +Enum(sanitize_coverage) String(trace-pc) Value(SANITIZE_COV_TRACE_PC) EnumValue -Enum(sanitize_coverage) String(trace-cmp) Value(SANITIZE_COV_TRACE_CMP) Set(2) +Enum(sanitize_coverage) String(trace-cmp) Value(SANITIZE_COV_TRACE_CMP) fasan-shadow-offset= Common Joined RejectNegative Var(common_deferred_options) Defer --- gcc/testsuite/gcc.dg/sancov/pr104158-7.c.jj 2022-01-23 17:56:44.179294117 +0100 +++ gcc/testsuite/gcc.dg/sancov/pr104158-7.c 2022-01-23 17:55:58.659930113 +0100 @@ -1,5 +1,11 @@ /* PR sanitizer/104158 */ /* { dg-do compile } */ /* { dg-options "-fsanitize-coverage=trace-cmp,trace-cmp -fdump-tree-optimized" } */ -/* { dg-error "invalid argument in option '-fsanitize-coverage=trace-cmp,trace-cmp'" "" { target *-*-* } 0 } */ -/* { dg-message "'trace-cmp' specified multiple times in the same option" "" { target *-*-* } 0 } */ +/* { dg-final { scan-tree-dump "__sanitizer_cov_trace_cmp" "optimized" } } */ +/* { dg-final { scan-tree-dump-not "__sanitizer_cov_trace_pc" "optimized" } } */ + +int +foo (int a, int b) +{ + return a == b; +}