From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from rock.gnat.com (rock.gnat.com [IPv6:2620:20:4000:0:a9e:1ff:fe9b:1d1]) by sourceware.org (Postfix) with ESMTPS id 5C6EA3851C3A for ; Fri, 29 Jul 2022 06:27:39 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 5C6EA3851C3A Received: from localhost (localhost.localdomain [127.0.0.1]) by filtered-rock.gnat.com (Postfix) with ESMTP id 0408E1168D2; Fri, 29 Jul 2022 02:27:38 -0400 (EDT) X-Virus-Scanned: Debian amavisd-new at gnat.com Received: from rock.gnat.com ([127.0.0.1]) by localhost (rock.gnat.com [127.0.0.1]) (amavisd-new, port 10024) with LMTP id pUSQSLdYpqX6; Fri, 29 Jul 2022 02:27:37 -0400 (EDT) Received: from free.home (tron.gnat.com [IPv6:2620:20:4000:0:46a8:42ff:fe0e:e294]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by rock.gnat.com (Postfix) with ESMTPS id B58551168CD; Fri, 29 Jul 2022 02:27:37 -0400 (EDT) Received: from livre (livre.home [172.31.160.2]) by free.home (8.15.2/8.15.2) with ESMTPS id 26T6RTFE1852044 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 29 Jul 2022 03:27:29 -0300 From: Alexandre Oliva To: gcc-patches@gcc.gnu.org Cc: Jeremy Bennett , Craig Blackmore , Graham Markall , Martin Jambor , Jan Hubicka , Richard Biener , Jim Wilson Subject: [PATCH v2 06/10] Introduce strub: attributes Organization: Free thinker, does not speak for AdaCore References: Errors-To: aoliva@lxoliva.fsfla.org Date: Fri, 29 Jul 2022 03:27:29 -0300 In-Reply-To: (Alexandre Oliva's message of "Fri, 29 Jul 2022 03:16:41 -0300") Message-ID: User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/25.2 (gnu/linux) MIME-Version: 1.0 Content-Type: text/plain X-Scanned-By: MIMEDefang 2.84 X-Spam-Status: No, score=-12.3 required=5.0 tests=BAYES_00, GIT_PATCH_0, KAM_DMARC_STATUS, SPF_HELO_NONE, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) 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-List-Received-Date: Fri, 29 Jul 2022 06:27:41 -0000 Ada already has support for the strub attributes stubbed-out, and the front-end code already has support for them and their effects in the type system. for gcc/ChangeLog * attribs.cc: Include ipa-strub.h. (decl_attributes): Support applying attributes to function type, rather than pointer type, at handler's request. (comp_type_attributes): Combine strub_comptypes and target comp_type results. for gcc/c-family/ChangeLog * c-attribs.cc: Include ipa-strub.h. (handle_strub_attribute): New. (c_common_attribute_table): Add strub. for gcc/ada/ChangeLog * gcc-interface/utils.cc: Include ipa-strub.h. (handle_strub_attribute): New. (gnat_internal_attribute_table): Add strub. diff --git a/gcc/attribs.cc b/gcc/attribs.cc index fb89616ff296b..d559cfc1b9f4e 100644 --- a/gcc/attribs.cc +++ b/gcc/attribs.cc @@ -27,6 +27,7 @@ along with GCC; see the file COPYING3. If not see #include "diagnostic-core.h" #include "attribs.h" #include "fold-const.h" +#include "ipa-strub.h" #include "stor-layout.h" #include "langhooks.h" #include "plugin.h" @@ -774,12 +775,11 @@ decl_attributes (tree *node, tree attributes, int flags, flags &= ~(int) ATTR_FLAG_TYPE_IN_PLACE; } - if (spec->function_type_required && TREE_CODE (*anode) != FUNCTION_TYPE - && TREE_CODE (*anode) != METHOD_TYPE) + if (spec->function_type_required + && !FUNC_OR_METHOD_TYPE_P (*anode)) { if (TREE_CODE (*anode) == POINTER_TYPE - && (TREE_CODE (TREE_TYPE (*anode)) == FUNCTION_TYPE - || TREE_CODE (TREE_TYPE (*anode)) == METHOD_TYPE)) + && FUNC_OR_METHOD_TYPE_P (TREE_TYPE (*anode))) { /* OK, this is a bit convoluted. We can't just make a copy of the pointer type and modify its TREE_TYPE, because if @@ -887,7 +887,24 @@ decl_attributes (tree *node, tree attributes, int flags, TYPE_NAME (tt) = *node; } - *anode = cur_and_last_decl[0]; + if (*anode != cur_and_last_decl[0]) + { + /* Even if !spec->function_type_required, allow the attribute + handler to request the attribute to be applied to the function + type, rather than to the function pointer type, by setting + cur_and_last_decl[0] to the function type. */ + if (!fn_ptr_tmp + && POINTER_TYPE_P (*anode) + && TREE_TYPE (*anode) == cur_and_last_decl[0] + && FUNC_OR_METHOD_TYPE_P (TREE_TYPE (*anode))) + { + fn_ptr_tmp = TREE_TYPE (*anode); + fn_ptr_quals = TYPE_QUALS (*anode); + anode = &fn_ptr_tmp; + } + *anode = cur_and_last_decl[0]; + } + if (ret == error_mark_node) { warning (OPT_Wattributes, "%qE attribute ignored", name); @@ -1491,9 +1508,20 @@ comp_type_attributes (const_tree type1, const_tree type2) if ((lookup_attribute ("nocf_check", TYPE_ATTRIBUTES (type1)) != NULL) ^ (lookup_attribute ("nocf_check", TYPE_ATTRIBUTES (type2)) != NULL)) return 0; + int strub_ret = strub_comptypes (CONST_CAST_TREE (type1), + CONST_CAST_TREE (type2)); + if (strub_ret == 0) + return strub_ret; /* As some type combinations - like default calling-convention - might be compatible, we have to call the target hook to get the final result. */ - return targetm.comp_type_attributes (type1, type2); + int target_ret = targetm.comp_type_attributes (type1, type2); + if (target_ret == 0) + return target_ret; + if (strub_ret == 2 || target_ret == 2) + return 2; + if (strub_ret == 1 && target_ret == 1) + return 1; + gcc_unreachable (); } /* PREDICATE acts as a function of type: diff --git a/gcc/c-family/c-attribs.cc b/gcc/c-family/c-attribs.cc index e4f1d3542f378..08c7d71f827a2 100644 --- a/gcc/c-family/c-attribs.cc +++ b/gcc/c-family/c-attribs.cc @@ -41,6 +41,7 @@ along with GCC; see the file COPYING3. If not see #include "common/common-target.h" #include "langhooks.h" #include "tree-inline.h" +#include "ipa-strub.h" #include "toplev.h" #include "tree-iterator.h" #include "opts.h" @@ -69,6 +70,7 @@ static tree handle_asan_odr_indicator_attribute (tree *, tree, tree, int, static tree handle_stack_protect_attribute (tree *, tree, tree, int, bool *); static tree handle_no_stack_protector_function_attribute (tree *, tree, tree, int, bool *); +static tree handle_strub_attribute (tree *, tree, tree, int, bool *); static tree handle_noinline_attribute (tree *, tree, tree, int, bool *); static tree handle_noclone_attribute (tree *, tree, tree, int, bool *); static tree handle_nocf_check_attribute (tree *, tree, tree, int, bool *); @@ -314,6 +316,8 @@ const struct attribute_spec c_common_attribute_table[] = { "no_stack_protector", 0, 0, true, false, false, false, handle_no_stack_protector_function_attribute, attr_stack_protect_exclusions }, + { "strub", 0, 1, false, true, false, true, + handle_strub_attribute, NULL }, { "noinline", 0, 0, true, false, false, false, handle_noinline_attribute, attr_noinline_exclusions }, @@ -1327,6 +1331,84 @@ handle_noipa_attribute (tree *node, tree name, tree, int, bool *no_add_attrs) return NULL_TREE; } +/* Handle a "strub" attribute; arguments as in + struct attribute_spec.handler. */ + +static tree +handle_strub_attribute (tree *node, tree name, + tree args, + int ARG_UNUSED (flags), bool *no_add_attrs) +{ + bool enable = true; + + if (args && FUNCTION_POINTER_TYPE_P (*node)) + *node = TREE_TYPE (*node); + + if (args && FUNC_OR_METHOD_TYPE_P (*node)) + { + switch (strub_validate_fn_attr_parm (TREE_VALUE (args))) + { + case 1: + case 2: + enable = true; + break; + + case 0: + warning (OPT_Wattributes, + "%qE attribute ignored because of argument %qE", + name, TREE_VALUE (args)); + *no_add_attrs = true; + enable = false; + break; + + case -1: + case -2: + enable = false; + break; + + default: + gcc_unreachable (); + } + + args = TREE_CHAIN (args); + } + + if (args) + { + warning (OPT_Wattributes, + "ignoring attribute %qE because of excess arguments" + " starting at %qE", + name, TREE_VALUE (args)); + *no_add_attrs = true; + enable = false; + } + + /* Warn about unmet expectations that the strub attribute works like a + qualifier. ??? Could/should we extend it to the element/field types + here? */ + if (TREE_CODE (*node) == ARRAY_TYPE + || VECTOR_TYPE_P (*node) + || TREE_CODE (*node) == COMPLEX_TYPE) + warning (OPT_Wattributes, + "attribute %qE does not apply to elements" + " of non-scalar type %qT", + name, *node); + else if (RECORD_OR_UNION_TYPE_P (*node)) + warning (OPT_Wattributes, + "attribute %qE does not apply to fields" + " of aggregate type %qT", + name, *node); + + /* If we see a strub-enabling attribute, and we're at the default setting, + implicitly or explicitly, note that the attribute was seen, so that we can + reduce the compile-time overhead to nearly zero when the strub feature is + not used. */ + if (enable && flag_strub < -2) + flag_strub += 2; + + return NULL_TREE; +} + /* Handle a "noinline" attribute; arguments as in struct attribute_spec.handler. */ diff --git a/gcc/ada/gcc-interface/utils.cc b/gcc/ada/gcc-interface/utils.cc index a57143021a79e..36b1345530d71 100644 --- a/gcc/ada/gcc-interface/utils.cc +++ b/gcc/ada/gcc-interface/utils.cc @@ -39,6 +39,7 @@ #include "varasm.h" #include "toplev.h" #include "opts.h" +#include "ipa-strub.h" #include "output.h" #include "debug.h" #include "convert.h" @@ -6601,9 +6602,77 @@ handle_no_stack_protector_attribute (tree *node, tree name, tree, int, struct attribute_spec.handler. */ static tree -handle_strub_attribute (tree *, tree, tree, int, bool *no_add_attrs) +handle_strub_attribute (tree *node, tree name, + tree args, + int ARG_UNUSED (flags), bool *no_add_attrs) { - *no_add_attrs = true; + bool enable = true; + + if (args && FUNCTION_POINTER_TYPE_P (*node)) + *node = TREE_TYPE (*node); + + if (args && FUNC_OR_METHOD_TYPE_P (*node)) + { + switch (strub_validate_fn_attr_parm (TREE_VALUE (args))) + { + case 1: + case 2: + enable = true; + break; + + case 0: + warning (OPT_Wattributes, + "%qE attribute ignored because of argument %qE", + name, TREE_VALUE (args)); + *no_add_attrs = true; + enable = false; + break; + + case -1: + case -2: + enable = false; + break; + + default: + gcc_unreachable (); + } + + args = TREE_CHAIN (args); + } + + if (args) + { + warning (OPT_Wattributes, + "ignoring attribute %qE because of excess arguments" + " starting at %qE", + name, TREE_VALUE (args)); + *no_add_attrs = true; + enable = false; + } + + /* Warn about unmet expectations that the strub attribute works like a + qualifier. ??? Could/should we extend it to the element/field types + here? */ + if (TREE_CODE (*node) == ARRAY_TYPE + || VECTOR_TYPE_P (*node) + || TREE_CODE (*node) == COMPLEX_TYPE) + warning (OPT_Wattributes, + "attribute %qE does not apply to elements" + " of non-scalar type %qT", + name, *node); + else if (RECORD_OR_UNION_TYPE_P (*node)) + warning (OPT_Wattributes, + "attribute %qE does not apply to fields" + " of aggregate type %qT", + name, *node); + + /* If we see a strub-enabling attribute, and we're at the default setting, + implicitly or explicitly, note that the attribute was seen, so that we can + reduce the compile-time overhead to nearly zero when the strub feature is + not used. */ + if (enable && flag_strub < -2) + flag_strub += 2; + return NULL_TREE; } -- Alexandre Oliva, happy hacker https://FSFLA.org/blogs/lxo/ Free Software Activist GNU Toolchain Engineer Disinformation flourishes because many people care deeply about injustice but very few check the facts. Ask me about