Add a simulate_builin_function_decl langhook
authorRichard Sandiford <richard.sandiford@arm.com>
Tue, 29 Oct 2019 08:39:33 +0000 (08:39 +0000)
committerRichard Sandiford <rsandifo@gcc.gnu.org>
Tue, 29 Oct 2019 08:39:33 +0000 (08:39 +0000)
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.

2019-10-29  Richard Sandiford  <richard.sandiford@arm.com>

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 (cxx_simulate_builtin_function_decl): New function.
* cp-objcp-common.h (LANG_HOOKS_SIMULATE_BUILTIN_FUNCTION_DECL): Define
to the above.

From-SVN: r277554

12 files changed:
gcc/ChangeLog
gcc/c/ChangeLog
gcc/c/c-decl.c
gcc/c/c-objc-common.h
gcc/c/c-tree.h
gcc/cp/ChangeLog
gcc/cp/cp-objcp-common.h
gcc/cp/cp-tree.h
gcc/cp/decl.c
gcc/langhooks-def.h
gcc/langhooks.c
gcc/langhooks.h

index b61be7ce07481f97a7260238ef4a31915c3128c7..e7d69ac896f1f061e1cfefe2c736dbb7142bb964 100644 (file)
@@ -1,3 +1,18 @@
+2019-10-29  Richard Sandiford  <richard.sandiford@arm.com>
+
+       * 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.
+
 2019-10-29  Jakub Jelinek  <jakub@redhat.com>
 
        * doc/install.texi (--enable-offload-targets): Fix up a typo in the
index 087090f1c85e649952d758ee4a20c87d25620dc0..3b0e3baf58aeb0a0a7212566598761fd8226d0e6 100644 (file)
@@ -1,3 +1,10 @@
+2019-10-29  Richard Sandiford  <richard.sandiford@arm.com>
+
+       * 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.
+
 2019-10-28  Martin Sebor  <msebor@redhat.com>
 
        PR c/66970
index e76ed26840f7c4883b380c2a4ca03b4c64030051..1013996194c6ac191b07cae8987e7c8256d25b7e 100644 (file)
@@ -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);
+}
 \f
 /* 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 f5e820420f6b0c6322230c727ba612d95b826f5d..8d3bcc2fdf127d88a3994bb2f29bbc1fb6c21a32 100644 (file)
@@ -60,6 +60,9 @@ along with GCC; see the file COPYING3.  If not see
 #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 dae2979d482c06c0b0ec5203e99d98db82102b2f..d01d4224fdde791089f46ac1840849562e0d1bff 100644 (file)
@@ -579,6 +579,7 @@ extern struct c_declarator *set_array_declarator_inner (struct c_declarator *,
                                                        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 143ddbbfa8fda8eda69f0c91ce173321a31c5b86..02cb6f3bf5b873bd03d5d4dad69b77eca3f1c21e 100644 (file)
@@ -1,3 +1,10 @@
+2019-10-29  Richard Sandiford  <richard.sandiford@arm.com>
+
+       * cp-tree.h (cxx_simulate_builtin_function_decl): Declare.
+       * decl.c (cxx_simulate_builtin_function_decl): New function.
+       * cp-objcp-common.h (LANG_HOOKS_SIMULATE_BUILTIN_FUNCTION_DECL): Define
+       to the above.
+
 2019-10-28  Martin Sebor  <msebor@redhat.com>
 
        PR c/66970
index 89a889a7dc9e5c1ffdb0cd7b465153ba0559615d..1827e53e73ade399390666bb65f829b6d322e985 100644 (file)
@@ -100,6 +100,9 @@ extern tree cxx_make_type_hook                      (tree_code);
 #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
index 7e0c41c222e267f23474ec7d71f437111cb6edbf..37b954a6c6f33058ef4a5539a77f0ff18c55d384 100644 (file)
@@ -6485,6 +6485,7 @@ extern tmpl_spec_kind current_tmpl_spec_kind      (int);
 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 827534c900c1acde76181f41c00904a0556685d5..dccde80b1a78502142a0895b381d22073b85046c 100644 (file)
@@ -4687,6 +4687,19 @@ cxx_builtin_function_ext_scope (tree decl)
   return decl;
 }
 
+/* Implement LANG_HOOKS_SIMULATE_BUILTIN_FUNCTION_DECL.  */
+
+tree
+cxx_simulate_builtin_function_decl (tree decl)
+{
+  retrofit_lang_decl (decl);
+
+  DECL_ARTIFICIAL (decl) = 1;
+  SET_DECL_LANGUAGE (decl, lang_cplusplus);
+  DECL_CONTEXT (decl) = FROB_CONTEXT (current_namespace);
+  return pushdecl (decl);
+}
+
 /* Generate a FUNCTION_DECL with the typical flags for a runtime library
    function.  Not called directly.  */
 
index c5dc83d1cc844f0bbc45b37dfdee19c9844b3fc7..af0c1b359c75eef6381274c1d6bff8a4760d6485 100644 (file)
@@ -122,6 +122,7 @@ extern int lhd_type_dwarf_attribute (const_tree, int);
 #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
@@ -342,6 +343,7 @@ extern void lhd_end_section (void);
   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 89fb5bc3ad80b8922a0e7bbead5fde2a23022371..2230e151e6318f47f525b3a2d289e4a9860798db 100644 (file)
@@ -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 *name,
   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 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_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 97e3186a41d3ae40c865faa76cdda8969a7d2c74..76f530eaeaf2acfe5db4d8384d5cef129c141da3 100644 (file)
@@ -504,6 +504,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);
 
@@ -572,6 +581,8 @@ extern tree add_builtin_function_ext_scope (const char *name, tree type,
                                            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.  */