From patchwork Mon Oct 14 18:46:46 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Richard Sandiford X-Patchwork-Id: 1176582 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=gcc.gnu.org (client-ip=209.132.180.131; helo=sourceware.org; envelope-from=gcc-patches-return-510932-incoming=patchwork.ozlabs.org@gcc.gnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=arm.com Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.b="F0Y7WJ9g"; dkim-atps=neutral Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 46sSGH6Sxjz9sP4 for ; Tue, 15 Oct 2019 05:47:02 +1100 (AEDT) DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:from :to:subject:references:date:in-reply-to:message-id:mime-version :content-type; q=dns; s=default; b=ub418bAD0pHuY+virjLPV7Qa0Rpq/ bnBFzRzp8xQYOjUR1CTSG5BhnO9tnJRmuPLns3+/YM2DTGvqJXvHjAgPvfIURB5W RDNy9nY24h8yv+C1rqSkuhzFCivA0P/nQ4aC8i90/XiD+kgl84alVBbb3St+7gDs yILrpgoA5/3Fh0= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:from :to:subject:references:date:in-reply-to:message-id:mime-version :content-type; s=default; bh=JSIt2Jq5aiP9WDh4H5a3WYAZ42s=; b=F0Y 7WJ9gIHaiXpsIKT6nu5PBrpl4lRY2UvvnytUqNMWOX2OFJ7tLtbNoQyVop0a7HbD 6gUeFxa1/LkVTVjclEdiHhqYu+sYrbdgprVOmyZVYcmFXvXdrtPBXq30dzzk8s9S M2+l9ACfrPShFBe3riENT8JdhhdUk2VkmOwGl05A= Received: (qmail 79518 invoked by alias); 14 Oct 2019 18:46:52 -0000 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org Received: (qmail 79492 invoked by uid 89); 14 Oct 2019 18:46:52 -0000 Authentication-Results: sourceware.org; auth=none X-Spam-SWARE-Status: No, score=-9.1 required=5.0 tests=AWL, BAYES_00, GIT_PATCH_2, GIT_PATCH_3, KAM_ASCII_DIVIDERS, KAM_SHORT autolearn=ham version=3.3.1 spammy=quoted, deliberately, UD:cp-tree.h, needing X-HELO: foss.arm.com Received: from foss.arm.com (HELO foss.arm.com) (217.140.110.172) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Mon, 14 Oct 2019 18:46:49 +0000 Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id A6C7A337 for ; Mon, 14 Oct 2019 11:46:47 -0700 (PDT) Received: from localhost (e121540-lin.manchester.arm.com [10.32.98.126]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 312293F6C4 for ; Mon, 14 Oct 2019 11:46:47 -0700 (PDT) From: Richard Sandiford To: gcc-patches@gcc.gnu.org Mail-Followup-To: gcc-patches@gcc.gnu.org, richard.sandiford@arm.com Subject: Ping: Add a simulate_builin_function_decl langhook References: Date: Mon, 14 Oct 2019 19:46:46 +0100 In-Reply-To: (Richard Sandiford's message of "Thu, 26 Sep 2019 13:04:11 +0100") Message-ID: User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/26.1 (gnu/linux) MIME-Version: 1.0 X-IsSubscribed: yes Ping See also https://gcc.gnu.org/ml/gcc-patches/2019-10/msg00413.html for more details about why this seemed like a good idea. A shorter version of that message (well, it started out that way :-)) is that it lets us use: #ifndef _ARM_SVE_H_ #define _ARM_SVE_H_ #include typedef __fp16 float16_t; typedef float float32_t; typedef double float64_t; #pragma GCC aarch64 "arm_sve.h" #endif as the full intrinsics header file. Rather than have GCC call: add_builtin_function ("__builtin_aarch64_svarsd_s16_n_x", fntype, code, BUILT_IN_MD, NULL, attrs); at start-up and having the header file provide an inline wrapper like: __extension__ extern __inline svint8_t __attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) svasrd_n_s16_x (svbool_t __a, svint8_t __b, int64_t __c) { return __builtin_aarch64_svasrd_n_s16_x (__a, __b, __c); } we can just have GCC call: simulate_builtin_function_decl (input_location, "svasrd_n_s16_x", fntype, code, NULL, attrs); when the header pragma is invoked. When repeated for thousands of functions, this significantly reduces the amount of code needed. It also gives quicker start-up times (because functions are only registered when they're needed) and makes arm_sve.h compile more quickly (because there's less code to parse). Another benefit is that inline wrappers don't show up in error messages. E.g.: #include int8x8_t foo (int16x8_t x, int y) { return vqrshrn_n_s16 (x, y); } gives: In file included from foo.c:3:10: In function 'vqrshrn_n_s16', inlined from 'foo' at foo.c:2: include/arm_neon.h:24419:10: error: argument 2 must be a constant immediate 24419 | return (int8x8_t) __builtin_aarch64_sqrshrn_nv8hi (__a, __b); | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ where the quoted line is the inline wrapper in arm_neon.h rather than the user's code. An SVE example like: #include svint16_t foo (svbool_t pg, svint16_t x, int y) { return svasrd_x (pg, x, y); } instead gives: foo.c: In function 'foo': foo.c:3:10: error: argument 3 of 'svasrd_x' must be an integer constant expression 3 | { return svasrd_x (pg, x, y); } | ^~~~~~~~ which seems more user-friendly. Thanks, Richard Richard Sandiford writes: > Although it's possible to define the SVE intrinsics in a normal header > file, it's much more convenient to define them directly in the compiler. > This also speeds up compilation and gives better error messages. > > The idea is therefore for arm_sve.h (the main intrinsics header file) > to have the pragma: > > #pragma GCC aarch64 "arm_sve.h" > > telling GCC to define (almost) everything arm_sve.h needs to define. > The target then needs a way of injecting new built-in function > declarations during compilation. > > The main hook for defining built-in functions is add_builtin_function. > This is designed for use at start-up, and so has various features that > are correct in that context but not for the pragma above: > > (1) the location is always BUILTINS_LOCATION, whereas for arm_sve.h > it ought to be the location of the pragma. > > (2) the function is only immediately visible if it's in the implementation > namespace, whereas the pragma is deliberately injecting functions > into the general namespace. > > (3) there's no attempt to emulate a normal function declaration in > C or C++, whereas functions declared by the pragma should be > checked in the same way as an open-coded declaration would be. > E.g. we should get an error if there was a previous incompatible > declaration. > > (4) in C++, the function is treated as extern "C" and so can't be > overloaded, whereas SVE intrinsics do use function overloading. > > This patch therefore adds a hook that targets can use to inject > the equivalent of a source-level function declaration, but bound > to a BUILT_IN_MD function. > > The main SVE intrinsic patch has tests to make sure that we report an > error for conflicting definitions that appear either before or after > including arm_sve.h. > > Tested on aarch64-linux-gnu and x86_64-linux-gnu. OK to install? > > Richard 2019-09-26 Richard Sandiford gcc/ * langhooks.h (lang_hooks::simulate_builtin_function_decl): New hook. (simulate_builtin_function_decl): Declare. * langhooks-def.h (LANG_HOOKS_SIMULATE_BUILTIN_FUNCTION_DECL): Define. (LANG_HOOKS_INITIALIZER): Include it. * langhooks.c (add_builtin_function_common): Rename to... (build_builtin_function): ...this. Add a location parameter and use it instead of BUILTINS_LOCATION. Remove the hook parameter and return the decl instead. (add_builtin_function): Update accordingly, passing the returned decl to the lang hook. (add_builtin_function_ext_scope): Likewise (simulate_builtin_function_decl): New function. gcc/c/ * c-tree.h (c_simulate_builtin_function_decl): Declare. * c-decl.c (c_simulate_builtin_function_decl): New function. * c-objc-common.h (LANG_HOOKS_SIMULATE_BUILTIN_FUNCTION_DECL): Define to the above. gcc/cp/ * cp-tree.h (cxx_simulate_builtin_function_decl): Declare. * decl.c (builtin_function_1): Add an is_simulated_source_decl parameter. When true, treat the function as a C++ function rather than as extern "C", and don't treat it as anticipated. (cxx_simulate_builtin_function_decl): New function. * cp-objcp-common.h (LANG_HOOKS_SIMULATE_BUILTIN_FUNCTION_DECL): Define to the above. Index: gcc/langhooks.h =================================================================== --- gcc/langhooks.h 2019-03-08 18:15:33.660751905 +0000 +++ gcc/langhooks.h 2019-09-26 13:02:42.543520465 +0100 @@ -494,6 +494,15 @@ struct lang_hooks backend must add all of the builtins at program initialization time. */ tree (*builtin_function_ext_scope) (tree decl); + /* Do language-specific processing for target-specific built-in + function DECL, so that it is defined in the global scope (only) + and is available without needing to be explicitly declared. + + This is intended for targets that want to inject declarations of + built-in functions into the source language (such as in response + to a pragma) rather than providing them in the source language itself. */ + tree (*simulate_builtin_function_decl) (tree decl); + /* Used to set up the tree_contains_structure array for a frontend. */ void (*init_ts) (void); @@ -562,6 +571,8 @@ extern tree add_builtin_function_ext_sco enum built_in_class cl, const char *library_name, tree attrs); +extern tree simulate_builtin_function_decl (location_t, const char *, tree, + int, const char *, tree); extern tree add_builtin_type (const char *name, tree type); /* Language helper functions. */ Index: gcc/langhooks-def.h =================================================================== --- gcc/langhooks-def.h 2019-03-08 18:15:39.328730361 +0000 +++ gcc/langhooks-def.h 2019-09-26 13:02:42.543520465 +0100 @@ -122,6 +122,7 @@ #define LANG_HOOKS_TREE_SIZE lhd_tree_s #define LANG_HOOKS_TYPES_COMPATIBLE_P lhd_types_compatible_p #define LANG_HOOKS_BUILTIN_FUNCTION lhd_builtin_function #define LANG_HOOKS_BUILTIN_FUNCTION_EXT_SCOPE LANG_HOOKS_BUILTIN_FUNCTION +#define LANG_HOOKS_SIMULATE_BUILTIN_FUNCTION_DECL LANG_HOOKS_BUILTIN_FUNCTION #define LANG_HOOKS_EXPR_TO_DECL lhd_expr_to_decl #define LANG_HOOKS_TO_TARGET_CHARSET lhd_to_target_charset #define LANG_HOOKS_INIT_TS lhd_do_nothing @@ -338,6 +339,7 @@ #define LANG_HOOKS_INITIALIZER { \ LANG_HOOKS_GIMPLIFY_EXPR, \ LANG_HOOKS_BUILTIN_FUNCTION, \ LANG_HOOKS_BUILTIN_FUNCTION_EXT_SCOPE, \ + LANG_HOOKS_SIMULATE_BUILTIN_FUNCTION_DECL, \ LANG_HOOKS_INIT_TS, \ LANG_HOOKS_EXPR_TO_DECL, \ LANG_HOOKS_EH_PERSONALITY, \ Index: gcc/langhooks.c =================================================================== --- gcc/langhooks.c 2019-08-25 19:10:35.194159619 +0100 +++ gcc/langhooks.c 2019-09-26 13:02:42.543520465 +0100 @@ -599,19 +599,16 @@ lhd_omp_mappable_type (tree type) return true; } -/* Common function for add_builtin_function and - add_builtin_function_ext_scope. */ +/* Common function for add_builtin_function, add_builtin_function_ext_scope + and simulate_builtin_function_decl. */ + static tree -add_builtin_function_common (const char *name, - tree type, - int function_code, - enum built_in_class cl, - const char *library_name, - tree attrs, - tree (*hook) (tree)) +build_builtin_function (location_t location, const char *name, tree type, + int function_code, enum built_in_class cl, + const char *library_name, tree attrs) { tree id = get_identifier (name); - tree decl = build_decl (BUILTINS_LOCATION, FUNCTION_DECL, id, type); + tree decl = build_decl (location, FUNCTION_DECL, id, type); TREE_PUBLIC (decl) = 1; DECL_EXTERNAL (decl) = 1; @@ -632,8 +629,7 @@ add_builtin_function_common (const char else decl_attributes (&decl, NULL_TREE, 0); - return hook (decl); - + return decl; } /* Create a builtin function. */ @@ -646,9 +642,9 @@ add_builtin_function (const char *name, const char *library_name, tree attrs) { - return add_builtin_function_common (name, type, function_code, cl, - library_name, attrs, - lang_hooks.builtin_function); + tree decl = build_builtin_function (BUILTINS_LOCATION, name, type, + function_code, cl, library_name, attrs); + return lang_hooks.builtin_function (decl); } /* Like add_builtin_function, but make sure the scope is the external scope. @@ -666,9 +662,40 @@ add_builtin_function_ext_scope (const ch const char *library_name, tree attrs) { - return add_builtin_function_common (name, type, function_code, cl, - library_name, attrs, - lang_hooks.builtin_function_ext_scope); + tree decl = build_builtin_function (BUILTINS_LOCATION, name, type, + function_code, cl, library_name, attrs); + return lang_hooks.builtin_function_ext_scope (decl); +} + +/* Simulate a declaration of a target-specific built-in function at + location LOCATION, as though it had been declared directly in the + source language. NAME is the name of the function, TYPE is its function + type, FUNCTION_CODE is the target-specific function code, LIBRARY_NAME + is the name of the underlying library function (NULL if none) and + ATTRS is a list of function attributes. + + Return the decl of the declared function. */ + +tree +simulate_builtin_function_decl (location_t location, const char *name, + tree type, int function_code, + const char *library_name, tree attrs) +{ + tree decl = build_builtin_function (location, name, type, + function_code, BUILT_IN_MD, + library_name, attrs); + tree new_decl = lang_hooks.simulate_builtin_function_decl (decl); + + /* Give the front end a chance to create a new decl if necessary, + but if the front end discards the decl in favour of a conflicting + (erroneous) previous definition, return the decl that we tried but + failed to add. This allows the caller to process the returned decl + normally, even though the source code won't be able to use it. */ + if (TREE_CODE (new_decl) == FUNCTION_DECL + && fndecl_built_in_p (new_decl, function_code, BUILT_IN_MD)) + return new_decl; + + return decl; } tree Index: gcc/c/c-tree.h =================================================================== --- gcc/c/c-tree.h 2019-07-10 19:41:20.543944894 +0100 +++ gcc/c/c-tree.h 2019-09-26 13:02:42.539520492 +0100 @@ -579,6 +579,7 @@ extern struct c_declarator *set_array_de struct c_declarator *); extern tree c_builtin_function (tree); extern tree c_builtin_function_ext_scope (tree); +extern tree c_simulate_builtin_function_decl (tree); extern void shadow_tag (const struct c_declspecs *); extern void shadow_tag_warned (const struct c_declspecs *, int); extern tree start_enum (location_t, struct c_enum_contents *, tree); Index: gcc/c/c-decl.c =================================================================== --- gcc/c/c-decl.c 2019-09-21 13:56:06.983948786 +0100 +++ gcc/c/c-decl.c 2019-09-26 13:02:42.539520492 +0100 @@ -4481,6 +4481,16 @@ c_builtin_function_ext_scope (tree decl) return decl; } + +/* Implement LANG_HOOKS_SIMULATE_BUILTIN_FUNCTION_DECL. */ + +tree +c_simulate_builtin_function_decl (tree decl) +{ + tree type = TREE_TYPE (decl); + C_DECL_BUILTIN_PROTOTYPE (decl) = prototype_p (type); + return pushdecl (decl); +} /* Called when a declaration is seen that contains no names to declare. If its type is a reference to a structure, union or enum inherited Index: gcc/c/c-objc-common.h =================================================================== --- gcc/c/c-objc-common.h 2019-04-04 08:34:51.661939350 +0100 +++ gcc/c/c-objc-common.h 2019-09-26 13:02:42.539520492 +0100 @@ -60,6 +60,9 @@ #define LANG_HOOKS_MISSING_NORETURN_OK_P #define LANG_HOOKS_BUILTIN_FUNCTION c_builtin_function #undef LANG_HOOKS_BUILTIN_FUNCTION_EXT_SCOPE #define LANG_HOOKS_BUILTIN_FUNCTION_EXT_SCOPE c_builtin_function_ext_scope +#undef LANG_HOOKS_SIMULATE_BUILTIN_FUNCTION_DECL +#define LANG_HOOKS_SIMULATE_BUILTIN_FUNCTION_DECL \ + c_simulate_builtin_function_decl #undef LANG_HOOKS_EMITS_BEGIN_STMT #define LANG_HOOKS_EMITS_BEGIN_STMT true Index: gcc/cp/cp-tree.h =================================================================== --- gcc/cp/cp-tree.h 2019-09-26 08:38:00.759713359 +0100 +++ gcc/cp/cp-tree.h 2019-09-26 13:02:42.539520492 +0100 @@ -6461,6 +6461,7 @@ extern tmpl_spec_kind current_tmpl_spec_ extern tree cp_fname_init (const char *, tree *); extern tree cxx_builtin_function (tree decl); extern tree cxx_builtin_function_ext_scope (tree decl); +extern tree cxx_simulate_builtin_function_decl (tree); extern tree check_elaborated_type_specifier (enum tag_types, tree, bool); extern void warn_extern_redeclared_static (tree, tree); extern tree cxx_comdat_group (tree); Index: gcc/cp/decl.c =================================================================== --- gcc/cp/decl.c 2019-09-17 15:27:10.958069743 +0100 +++ gcc/cp/decl.c 2019-09-26 13:02:42.543520465 +0100 @@ -71,7 +71,6 @@ static tree grokvardecl (tree, tree, tre int, int, int, bool, int, tree, location_t); static void check_static_variable_definition (tree, tree); static void record_unknown_type (tree, const char *); -static tree builtin_function_1 (tree, tree, bool); static int member_function_or_else (tree, tree, enum overload_flags); static tree local_variable_p_walkfn (tree *, int *, void *); static const char *tag_name (enum tag_types); @@ -4567,8 +4566,12 @@ cp_make_fname_decl (location_t loc, tree return decl; } +/* IS_SIMULATED_DECL is true if the decl should simulate a global + declaration in the source language. */ + static tree -builtin_function_1 (tree decl, tree context, bool is_global) +builtin_function_1 (tree decl, tree context, bool is_global, + bool is_simulated_decl = false) { tree id = DECL_NAME (decl); const char *name = IDENTIFIER_POINTER (id); @@ -4576,7 +4579,10 @@ builtin_function_1 (tree decl, tree cont retrofit_lang_decl (decl); DECL_ARTIFICIAL (decl) = 1; - SET_DECL_LANGUAGE (decl, lang_c); + if (is_simulated_decl) + SET_DECL_LANGUAGE (decl, lang_cplusplus); + else + SET_DECL_LANGUAGE (decl, lang_c); /* Runtime library routines are, by definition, available in an external shared object. */ DECL_VISIBILITY (decl) = VISIBILITY_DEFAULT; @@ -4584,21 +4590,24 @@ builtin_function_1 (tree decl, tree cont DECL_CONTEXT (decl) = context; - /* A function in the user's namespace should have an explicit - declaration before it is used. Mark the built-in function as - anticipated but not actually declared. */ - if (name[0] != '_' || name[1] != '_') - DECL_ANTICIPATED (decl) = 1; - else if (strncmp (name + 2, "builtin_", strlen ("builtin_")) != 0) - { - size_t len = strlen (name); - - /* Treat __*_chk fortification functions as anticipated as well, - unless they are __builtin_*. */ - if (len > strlen ("___chk") - && memcmp (name + len - strlen ("_chk"), - "_chk", strlen ("_chk") + 1) == 0) + if (!is_simulated_decl) + { + /* A function in the user's namespace should have an explicit + declaration before it is used. Mark the built-in function as + anticipated but not actually declared. */ + if (name[0] != '_' || name[1] != '_') DECL_ANTICIPATED (decl) = 1; + else if (strncmp (name + 2, "builtin_", strlen ("builtin_")) != 0) + { + size_t len = strlen (name); + + /* Treat __*_chk fortification functions as anticipated as well, + unless they are __builtin_*. */ + if (len > strlen ("___chk") + && memcmp (name + len - strlen ("_chk"), + "_chk", strlen ("_chk") + 1) == 0) + DECL_ANTICIPATED (decl) = 1; + } } if (is_global) @@ -4650,6 +4659,14 @@ cxx_builtin_function_ext_scope (tree dec return builtin_function_1 (decl, NULL_TREE, true); } +/* Implement LANG_HOOKS_SIMULATE_BUILTIN_FUNCTION_DECL. */ + +tree +cxx_simulate_builtin_function_decl (tree decl) +{ + return builtin_function_1 (decl, NULL_TREE, true, true); +} + /* Generate a FUNCTION_DECL with the typical flags for a runtime library function. Not called directly. */ Index: gcc/cp/cp-objcp-common.h =================================================================== --- gcc/cp/cp-objcp-common.h 2019-03-08 18:15:25.000784821 +0000 +++ gcc/cp/cp-objcp-common.h 2019-09-26 13:02:42.539520492 +0100 @@ -100,6 +100,9 @@ #define LANG_HOOKS_POST_COMPILATION_PARS #define LANG_HOOKS_BUILTIN_FUNCTION cxx_builtin_function #undef LANG_HOOKS_BUILTIN_FUNCTION_EXT_SCOPE #define LANG_HOOKS_BUILTIN_FUNCTION_EXT_SCOPE cxx_builtin_function_ext_scope +#undef LANG_HOOKS_SIMULATE_BUILTIN_FUNCTION_DECL +#define LANG_HOOKS_SIMULATE_BUILTIN_FUNCTION_DECL \ + cxx_simulate_builtin_function_decl #undef LANG_HOOKS_TYPE_HASH_EQ #define LANG_HOOKS_TYPE_HASH_EQ cxx_type_hash_eq #undef LANG_HOOKS_COPY_LANG_QUALIFIERS