public inbox for gcc-cvs@sourceware.org
help / color / mirror / Atom feed
* [gcc/devel/rust/master] builtins: Cleanup initialization of builtins
@ 2022-12-01  8:12 Thomas Schwinge
  0 siblings, 0 replies; only message in thread
From: Thomas Schwinge @ 2022-12-01  8:12 UTC (permalink / raw)
  To: gcc-cvs

https://gcc.gnu.org/g:fc59d137491ce393797dfec1d8cd5251a41b5f67

commit fc59d137491ce393797dfec1d8cd5251a41b5f67
Author: Arthur Cohen <arthur.cohen@embecosm.com>
Date:   Thu Nov 3 15:02:37 2022 +0100

    builtins: Cleanup initialization of builtins
    
    This commit performs builtin initialization in a more "GCC-y" way, similarly to what the D frontend is doing. This way, we no longer have to worry about invalid attributes or types when initializing them by hand.

Diff:
---
 gcc/rust/backend/rust-builtins.cc                  | 350 ++++++++++++++-------
 gcc/rust/backend/rust-builtins.h                   | 118 ++++++-
 gcc/rust/backend/rust-compile-intrinsic.cc         |  41 ++-
 gcc/rust/rust-gcc.cc                               |   8 +-
 gcc/testsuite/rust/compile/torture/intrinsics-4.rs |   2 +-
 gcc/testsuite/rust/execute/torture/atomic_load.rs  |   4 +-
 gcc/testsuite/rust/execute/torture/atomic_store.rs |   4 +-
 7 files changed, 389 insertions(+), 138 deletions(-)

diff --git a/gcc/rust/backend/rust-builtins.cc b/gcc/rust/backend/rust-builtins.cc
index 66b3becc47a..ee3e42e6b53 100644
--- a/gcc/rust/backend/rust-builtins.cc
+++ b/gcc/rust/backend/rust-builtins.cc
@@ -14,8 +14,13 @@
 // along with GCC; see the file COPYING3.  If not see
 // <http://www.gnu.org/licenses/>.
 
+#include "rust-diagnostics.h"
+#include "rust-system.h"
 #include "rust-builtins.h"
 
+#include "target.h"
+#include "stringpool.h"
+
 namespace Rust {
 namespace Compile {
 
@@ -33,154 +38,275 @@ BuiltinsContext::get ()
 bool
 BuiltinsContext::lookup_simple_builtin (const std::string &name, tree *builtin)
 {
+  auto *to_search = &name;
+
   auto it = rust_intrinsic_to_gcc_builtin.find (name);
-  if (it == rust_intrinsic_to_gcc_builtin.end ())
-    return false;
+  if (it != rust_intrinsic_to_gcc_builtin.end ())
+    to_search = &it->second;
 
-  return lookup_gcc_builtin (it->second, builtin);
+  return lookup_gcc_builtin (*to_search, builtin);
 }
 
 BuiltinsContext::BuiltinsContext () { setup (); }
 
+/**
+ * Define a function type according to `builtin-types.def`
+ *
+ * *Heavily* inspired by the D frontend's `def_fn_type` function
+ */
 void
-BuiltinsContext::setup_overflow_fns ()
+BuiltinsContext::define_function_type (Type def_idx, Type ret_idx,
+				       bool is_variadic, size_t n, ...)
 {
-  tree overflow_type
-    = build_varargs_function_type_list (boolean_type_node, NULL_TREE);
-
-  define_builtin ("add_overflow", BUILT_IN_ADD_OVERFLOW,
-		  "__builtin_add_overflow", "add_overflow", overflow_type, 0);
-  define_builtin ("sub_overflow", BUILT_IN_SUB_OVERFLOW,
-		  "__builtin_sub_overflow", "sub_overflow", overflow_type, 0);
-  define_builtin ("mul_overflow", BUILT_IN_MUL_OVERFLOW,
-		  "__builtin_mul_overflow", "mul_overflow", overflow_type, 0);
+  va_list list;
+  va_start (list, n);
+
+  auto args = std::vector<tree> ();
+
+  for (size_t i = 0; i < n; i++)
+    {
+      auto arg_idx = va_arg (list, size_t);
+      auto arg_type = builtin_types[arg_idx];
+
+      args.emplace_back (arg_type);
+    }
+
+  auto return_type = builtin_types[ret_idx];
+  if (return_type == error_mark_node)
+    {
+      va_end (list);
+      return;
+    }
+
+  auto fn_type = NULL_TREE;
+  if (is_variadic)
+    fn_type = build_varargs_function_type_array (return_type, n, args.data ());
+  else
+    fn_type = build_function_type_array (return_type, n, args.data ());
+
+  builtin_types[def_idx] = fn_type;
+  va_end (list);
 }
 
-void
-BuiltinsContext::setup_math_fns ()
+// Taken directly from the D frontend
+static void
+build_c_type_nodes (void)
 {
-  tree math_function_type_f32
-    = build_function_type_list (float_type_node, float_type_node, NULL_TREE);
+  string_type_node = build_pointer_type (char_type_node);
+  const_string_type_node = build_pointer_type (
+    build_qualified_type (char_type_node, TYPE_QUAL_CONST));
+
+  if (strcmp (UINTMAX_TYPE, "unsigned int") == 0)
+    {
+      intmax_type_node = integer_type_node;
+      uintmax_type_node = unsigned_type_node;
+    }
+  else if (strcmp (UINTMAX_TYPE, "long unsigned int") == 0)
+    {
+      intmax_type_node = long_integer_type_node;
+      uintmax_type_node = long_unsigned_type_node;
+    }
+  else if (strcmp (UINTMAX_TYPE, "long long unsigned int") == 0)
+    {
+      intmax_type_node = long_long_integer_type_node;
+      uintmax_type_node = long_long_unsigned_type_node;
+    }
+  else
+    gcc_unreachable ();
 
-  define_builtin ("sinf32", BUILT_IN_SINF, "__builtin_sinf", "sinf",
-		  math_function_type_f32, builtin_const);
-  define_builtin ("sqrtf32", BUILT_IN_SQRTF, "__builtin_sqrtf", "sqrtf",
-		  math_function_type_f32, builtin_const);
+  signed_size_type_node = signed_type_for (size_type_node);
+  wint_type_node = unsigned_type_node;
+  pid_type_node = integer_type_node;
 }
 
+/**
+ * Define all builtin types in the `builtin_types` array
+ */
 void
-BuiltinsContext::setup_atomic_fns ()
+BuiltinsContext::define_builtin_types ()
 {
-  auto atomic_store_type
-    = build_varargs_function_type_list (void_type_node, NULL_TREE);
-  auto atomic_load_type = [] (tree ret_type_node) {
-    return build_function_type_list (ret_type_node,
-				     ptr_type_node, // const_ptr_type_node?
-				     integer_type_node, NULL_TREE);
+  // This is taken directly from the D frontend's handling of builtins
+  auto va_list_ref_type_node = build_reference_type (va_list_type_node);
+  auto va_list_arg_type_node = va_list_type_node;
+
+  build_c_type_nodes ();
+
+  auto builtin_type_for_size = [] (int size, bool unsignedp) {
+    tree type = lang_hooks.types.type_for_size (size, unsignedp);
+    return type ? type : error_mark_node;
   };
 
-  // FIXME: These should be the definition for the generic version of the
-  // atomic_store builtins, but I cannot get them to work properly. Revisit
-  // later. define_builtin ("atomic_store", BUILT_IN_ATOMIC_STORE,
-  // "__atomic_store", NULL,
-  //   atomic_store_type, 0);
-  // define_builtin ("atomic_store_n", BUILT_IN_ATOMIC_STORE_N,
-  // "__atomic_store_n",
-  //   NULL, atomic_store_type, 0);
-
-  define_builtin ("atomic_store_1", BUILT_IN_ATOMIC_STORE_1, "__atomic_store_1",
-		  NULL, atomic_store_type, 0);
-  define_builtin ("atomic_store_2", BUILT_IN_ATOMIC_STORE_2, "__atomic_store_2",
-		  NULL, atomic_store_type, 0);
-  define_builtin ("atomic_store_4", BUILT_IN_ATOMIC_STORE_4, "__atomic_store_4",
-		  NULL, atomic_store_type, 0);
-  define_builtin ("atomic_store_8", BUILT_IN_ATOMIC_STORE_8, "__atomic_store_8",
-		  NULL, atomic_store_type, 0);
-  define_builtin ("atomic_store_16", BUILT_IN_ATOMIC_STORE_16,
-		  "__atomic_store_16", NULL, atomic_store_type, 0);
-
-  define_builtin ("atomic_load_1", BUILT_IN_ATOMIC_LOAD_1, "__atomic_load_1",
-		  NULL, atomic_load_type (integer_type_node), 0);
-  define_builtin ("atomic_load_2", BUILT_IN_ATOMIC_LOAD_2, "__atomic_load_2",
-		  NULL, atomic_load_type (integer_type_node), 0);
-  define_builtin ("atomic_load_4", BUILT_IN_ATOMIC_LOAD_4, "__atomic_load_4",
-		  NULL, atomic_load_type (integer_type_node), 0);
-  define_builtin ("atomic_load_8", BUILT_IN_ATOMIC_LOAD_8, "__atomic_load_8",
-		  NULL, atomic_load_type (integer_type_node), 0);
+#define DEF_PRIMITIVE_TYPE(ENUM, VALUE) builtin_types[ENUM] = VALUE;
+#define DEF_FUNCTION_TYPE_0(ENUM, RETURN)                                      \
+  define_function_type (ENUM, RETURN, 0, 0);
+#define DEF_FUNCTION_TYPE_1(ENUM, RETURN, A1)                                  \
+  define_function_type (ENUM, RETURN, 0, 1, A1);
+#define DEF_FUNCTION_TYPE_2(ENUM, RETURN, A1, A2)                              \
+  define_function_type (ENUM, RETURN, 0, 2, A1, A2);
+#define DEF_FUNCTION_TYPE_3(ENUM, RETURN, A1, A2, A3)                          \
+  define_function_type (ENUM, RETURN, 0, 3, A1, A2, A3);
+#define DEF_FUNCTION_TYPE_4(ENUM, RETURN, A1, A2, A3, A4)                      \
+  define_function_type (ENUM, RETURN, 0, 4, A1, A2, A3, A4);
+#define DEF_FUNCTION_TYPE_5(ENUM, RETURN, A1, A2, A3, A4, A5)                  \
+  define_function_type (ENUM, RETURN, 0, 5, A1, A2, A3, A4, A5);
+#define DEF_FUNCTION_TYPE_6(ENUM, RETURN, A1, A2, A3, A4, A5, A6)              \
+  define_function_type (ENUM, RETURN, 0, 6, A1, A2, A3, A4, A5, A6);
+#define DEF_FUNCTION_TYPE_7(ENUM, RETURN, A1, A2, A3, A4, A5, A6, A7)          \
+  define_function_type (ENUM, RETURN, 0, 7, A1, A2, A3, A4, A5, A6, A7);
+#define DEF_FUNCTION_TYPE_8(ENUM, RETURN, A1, A2, A3, A4, A5, A6, A7, A8)      \
+  define_function_type (ENUM, RETURN, 0, 8, A1, A2, A3, A4, A5, A6, A7, A8);
+#define DEF_FUNCTION_TYPE_9(ENUM, RETURN, A1, A2, A3, A4, A5, A6, A7, A8, A9)  \
+  define_function_type (ENUM, RETURN, 0, 9, A1, A2, A3, A4, A5, A6, A7, A8, A9);
+#define DEF_FUNCTION_TYPE_10(ENUM, RETURN, A1, A2, A3, A4, A5, A6, A7, A8, A9, \
+			     A10)                                              \
+  define_function_type (ENUM, RETURN, 0, 10, A1, A2, A3, A4, A5, A6, A7, A8,   \
+			A9, A10);
+#define DEF_FUNCTION_TYPE_11(ENUM, RETURN, A1, A2, A3, A4, A5, A6, A7, A8, A9, \
+			     A10, A11)                                         \
+  define_function_type (ENUM, RETURN, 0, 11, A1, A2, A3, A4, A5, A6, A7, A8,   \
+			A9, A10, A11);
+#define DEF_FUNCTION_TYPE_VAR_0(ENUM, RETURN)                                  \
+  define_function_type (ENUM, RETURN, 1, 0);
+#define DEF_FUNCTION_TYPE_VAR_1(ENUM, RETURN, A1)                              \
+  define_function_type (ENUM, RETURN, 1, 1, A1);
+#define DEF_FUNCTION_TYPE_VAR_2(ENUM, RETURN, A1, A2)                          \
+  define_function_type (ENUM, RETURN, 1, 2, A1, A2);
+#define DEF_FUNCTION_TYPE_VAR_3(ENUM, RETURN, A1, A2, A3)                      \
+  define_function_type (ENUM, RETURN, 1, 3, A1, A2, A3);
+#define DEF_FUNCTION_TYPE_VAR_4(ENUM, RETURN, A1, A2, A3, A4)                  \
+  define_function_type (ENUM, RETURN, 1, 4, A1, A2, A3, A4);
+#define DEF_FUNCTION_TYPE_VAR_5(ENUM, RETURN, A1, A2, A3, A4, A5)              \
+  define_function_type (ENUM, RETURN, 1, 5, A1, A2, A3, A4, A5);
+#define DEF_FUNCTION_TYPE_VAR_6(ENUM, RETURN, A1, A2, A3, A4, A5, A6)          \
+  define_function_type (ENUM, RETURN, 1, 6, A1, A2, A3, A4, A5, A6);
+#define DEF_FUNCTION_TYPE_VAR_7(ENUM, RETURN, A1, A2, A3, A4, A5, A6, A7)      \
+  define_function_type (ENUM, RETURN, 1, 7, A1, A2, A3, A4, A5, A6, A7);
+#define DEF_FUNCTION_TYPE_VAR_11(ENUM, RETURN, A1, A2, A3, A4, A5, A6, A7, A8, \
+				 A9, A10, A11)                                 \
+  define_function_type (ENUM, RETURN, 1, 11, A1, A2, A3, A4, A5, A6, A7, A8,   \
+			A9, A10, A11);
+#define DEF_POINTER_TYPE(ENUM, TYPE)                                           \
+  builtin_types[ENUM] = build_pointer_type (builtin_types[TYPE]);
+
+#include "builtin-types.def"
+
+#undef DEF_PRIMITIVE_TYPE
+#undef DEF_FUNCTION_TYPE_1
+#undef DEF_FUNCTION_TYPE_2
+#undef DEF_FUNCTION_TYPE_3
+#undef DEF_FUNCTION_TYPE_4
+#undef DEF_FUNCTION_TYPE_5
+#undef DEF_FUNCTION_TYPE_6
+#undef DEF_FUNCTION_TYPE_7
+#undef DEF_FUNCTION_TYPE_8
+#undef DEF_FUNCTION_TYPE_9
+#undef DEF_FUNCTION_TYPE_10
+#undef DEF_FUNCTION_TYPE_11
+#undef DEF_FUNCTION_TYPE_VAR_0
+#undef DEF_FUNCTION_TYPE_VAR_1
+#undef DEF_FUNCTION_TYPE_VAR_2
+#undef DEF_FUNCTION_TYPE_VAR_3
+#undef DEF_FUNCTION_TYPE_VAR_4
+#undef DEF_FUNCTION_TYPE_VAR_5
+#undef DEF_FUNCTION_TYPE_VAR_6
+#undef DEF_FUNCTION_TYPE_VAR_7
+#undef DEF_FUNCTION_TYPE_VAR_11
+#undef DEF_POINTER_TYPE
+
+  builtin_types[Type::BT_LAST] = NULL_TREE;
 }
 
+/**
+ * Define all builtin attributes in the `builtin_types` array
+ */
 void
-BuiltinsContext::setup ()
+BuiltinsContext::define_builtin_attributes ()
+
 {
-  setup_math_fns ();
-  setup_overflow_fns ();
-  setup_atomic_fns ();
-
-  define_builtin ("unreachable", BUILT_IN_UNREACHABLE, "__builtin_unreachable",
-		  NULL, build_function_type (void_type_node, void_list_node),
-		  builtin_const | builtin_noreturn);
-
-  define_builtin ("abort", BUILT_IN_ABORT, "__builtin_abort", "abort",
-		  build_function_type (void_type_node, void_list_node),
-		  builtin_const | builtin_noreturn);
-
-  define_builtin ("breakpoint", BUILT_IN_TRAP, "__builtin_trap", "breakpoint",
-		  build_function_type (void_type_node, void_list_node),
-		  builtin_const | builtin_noreturn);
-
-  define_builtin ("memcpy", BUILT_IN_MEMCPY, "__builtin_memcpy", "memcpy",
-		  build_function_type_list (build_pointer_type (void_type_node),
-					    build_pointer_type (void_type_node),
-					    build_pointer_type (void_type_node),
-					    size_type_node, NULL_TREE),
-		  0);
-
-  define_builtin ("prefetch", BUILT_IN_PREFETCH, "__builtin_prefetch",
-		  "prefetch",
-		  build_varargs_function_type_list (
-		    build_pointer_type (const_ptr_type_node), NULL_TREE),
-		  builtin_const);
+  auto *built_in_attributes = builtin_attributes;
+
+#define DEF_ATTR_NULL_TREE(ENUM) built_in_attributes[(int) ENUM] = NULL_TREE;
+#define DEF_ATTR_INT(ENUM, VALUE)                                              \
+  built_in_attributes[ENUM] = build_int_cst (NULL_TREE, VALUE);
+#define DEF_ATTR_STRING(ENUM, VALUE)                                           \
+  built_in_attributes[ENUM] = build_string (strlen (VALUE), VALUE);
+#define DEF_ATTR_IDENT(ENUM, STRING)                                           \
+  built_in_attributes[ENUM] = get_identifier (STRING);
+#define DEF_ATTR_TREE_LIST(ENUM, PURPOSE, VALUE, CHAIN)                        \
+  built_in_attributes[ENUM]                                                    \
+    = tree_cons (built_in_attributes[PURPOSE], built_in_attributes[VALUE],     \
+		 built_in_attributes[CHAIN]);
+#include "builtin-attrs.def"
+#undef DEF_ATTR_NULL_TREE
+#undef DEF_ATTR_INT
+#undef DEF_ATTR_STRING
+#undef DEF_ATTR_IDENT
+#undef DEF_ATTR_TREE_LIST
 }
 
-static void
-handle_flags (tree decl, int flags)
+/**
+ * Define all builtin functions during the first initialization of the
+ * `BuiltinsContext`.
+ */
+void
+BuiltinsContext::define_builtins ()
 {
-  if (flags & builtin_const)
-    TREE_READONLY (decl) = 1;
-  if (flags & builtin_noreturn)
-    TREE_READONLY (decl) = 1;
-  if (flags & builtin_novops)
-    DECL_IS_NOVOPS (decl) = 1;
+  auto *built_in_attributes = builtin_attributes;
+  auto build_builtin = [this] (built_in_function fn_code, const char *fn_name,
+			       built_in_class fn_class, tree fn_type, bool both,
+			       bool fallback, tree attributes, bool implicit) {
+    if (fn_type == error_mark_node)
+      return;
+
+    static auto to_skip = strlen ("__builtin_");
+
+    auto libname = fn_name + to_skip;
+    auto decl = add_builtin_function (fn_name, fn_type, fn_code, fn_class,
+				      fallback ? libname : NULL, attributes);
+
+    set_builtin_decl (fn_code, decl, implicit);
+
+    builtin_functions.insert ({std::string (fn_name), decl});
+  };
+
+#define DEF_BUILTIN(ENUM, NAME, CLASS, TYPE, LIBTYPE, BOTH_P, FALLBACK_P,      \
+		    NONANSI_P, ATTRS, IMPLICIT, COND)                          \
+  if (NAME && COND)                                                            \
+    build_builtin (ENUM, NAME, CLASS, builtin_types[TYPE], BOTH_P, FALLBACK_P, \
+		   built_in_attributes[ATTRS], IMPLICIT);
+#include "builtins.def"
+#undef DEF_BUILTIN
 }
 
+/**
+ * Register direct mappings between Rust functions and GCC builtins
+ */
 void
-BuiltinsContext::define_builtin (const std::string rust_name,
-				 built_in_function bcode, const char *name,
-				 const char *libname, tree fntype, int flags)
+BuiltinsContext::register_rust_mappings ()
 {
-  tree decl = add_builtin_function (name, fntype, bcode, BUILT_IN_NORMAL,
-				    libname, NULL_TREE);
-  handle_flags (decl, flags);
-  set_builtin_decl (bcode, decl, true);
-
-  this->builtin_functions_[name] = decl;
-  if (libname != NULL)
-    {
-      decl = add_builtin_function (libname, fntype, bcode, BUILT_IN_NORMAL,
-				   NULL, NULL_TREE);
-      handle_flags (decl, flags);
+  rust_intrinsic_to_gcc_builtin = {
+    {"sinf32", "__builtin_sinf"},
+    {"sqrtf32", "__builtin_sqrtf"},
+    {"unreachable", "__builtin_unreachable"},
+    {"abort", "__builtin_abort"},
+  };
+}
 
-      this->builtin_functions_[libname] = decl;
-    }
+void
+BuiltinsContext::setup ()
+{
+  define_builtin_types ();
+  define_builtin_attributes ();
+  define_builtins ();
 
-  rust_intrinsic_to_gcc_builtin[rust_name] = name;
+  register_rust_mappings ();
 }
 
 bool
 BuiltinsContext::lookup_gcc_builtin (const std::string &name, tree *builtin)
 {
-  auto it = builtin_functions_.find (name);
-  if (it == builtin_functions_.end ())
+  auto it = builtin_functions.find (name);
+  if (it == builtin_functions.end ())
     return false;
 
   *builtin = it->second;
diff --git a/gcc/rust/backend/rust-builtins.h b/gcc/rust/backend/rust-builtins.h
index c2825107faf..5052edad51e 100644
--- a/gcc/rust/backend/rust-builtins.h
+++ b/gcc/rust/backend/rust-builtins.h
@@ -21,6 +21,7 @@
 #include "rust-tree.h"
 #include "langhooks.h"
 #include "tree.h"
+#include "selftest.h"
 
 namespace Rust {
 namespace Compile {
@@ -75,6 +76,7 @@ namespace Compile {
 //     _ => return None,
 // };
 // Some(cx.get_intrinsic(&llvm_name))
+
 class BuiltinsContext
 {
 public:
@@ -83,6 +85,110 @@ public:
   bool lookup_simple_builtin (const std::string &name, tree *builtin);
 
 private:
+  enum Type
+  {
+#define DEF_PRIMITIVE_TYPE(NAME, V) NAME,
+#define DEF_FUNCTION_TYPE_0(NAME, R) NAME,
+#define DEF_FUNCTION_TYPE_1(NAME, R, A1) NAME,
+#define DEF_FUNCTION_TYPE_2(NAME, R, A1, A2) NAME,
+#define DEF_FUNCTION_TYPE_3(NAME, R, A1, A2, A3) NAME,
+#define DEF_FUNCTION_TYPE_4(NAME, R, A1, A2, A3, A4) NAME,
+#define DEF_FUNCTION_TYPE_5(NAME, R, A1, A2, A3, A4, A5) NAME,
+#define DEF_FUNCTION_TYPE_6(NAME, R, A1, A2, A3, A4, A5, A6) NAME,
+#define DEF_FUNCTION_TYPE_7(NAME, R, A1, A2, A3, A4, A5, A6, A7) NAME,
+#define DEF_FUNCTION_TYPE_8(NAME, R, A1, A2, A3, A4, A5, A6, A7, A8) NAME,
+#define DEF_FUNCTION_TYPE_9(NAME, R, A1, A2, A3, A4, A5, A6, A7, A8, A9) NAME,
+#define DEF_FUNCTION_TYPE_10(NAME, R, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10) \
+  NAME,
+#define DEF_FUNCTION_TYPE_11(NAME, R, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, \
+			     A11)                                              \
+  NAME,
+#define DEF_FUNCTION_TYPE_VAR_0(NAME, R) NAME,
+#define DEF_FUNCTION_TYPE_VAR_1(NAME, R, A1) NAME,
+#define DEF_FUNCTION_TYPE_VAR_2(NAME, R, A1, A2) NAME,
+#define DEF_FUNCTION_TYPE_VAR_3(NAME, R, A1, A2, A3) NAME,
+#define DEF_FUNCTION_TYPE_VAR_4(NAME, R, A1, A2, A3, A4) NAME,
+#define DEF_FUNCTION_TYPE_VAR_5(NAME, R, A1, A2, A3, A4, A5) NAME,
+#define DEF_FUNCTION_TYPE_VAR_6(NAME, R, A1, A2, A3, A4, A5, A6) NAME,
+#define DEF_FUNCTION_TYPE_VAR_7(NAME, R, A1, A2, A3, A4, A5, A6, A7) NAME,
+#define DEF_FUNCTION_TYPE_VAR_11(NAME, R, A1, A2, A3, A4, A5, A6, A7, A8, A9,  \
+				 A10, A11)                                     \
+  NAME,
+#define DEF_POINTER_TYPE(NAME, TYPE) NAME,
+
+#include "builtin-types.def"
+
+#undef DEF_PRIMITIVE_TYPE
+#undef DEF_FUNCTION_TYPE_0
+#undef DEF_FUNCTION_TYPE_1
+#undef DEF_FUNCTION_TYPE_2
+#undef DEF_FUNCTION_TYPE_3
+#undef DEF_FUNCTION_TYPE_4
+#undef DEF_FUNCTION_TYPE_5
+#undef DEF_FUNCTION_TYPE_6
+#undef DEF_FUNCTION_TYPE_7
+#undef DEF_FUNCTION_TYPE_8
+#undef DEF_FUNCTION_TYPE_9
+#undef DEF_FUNCTION_TYPE_10
+#undef DEF_FUNCTION_TYPE_11
+#undef DEF_FUNCTION_TYPE_VAR_0
+#undef DEF_FUNCTION_TYPE_VAR_1
+#undef DEF_FUNCTION_TYPE_VAR_2
+#undef DEF_FUNCTION_TYPE_VAR_3
+#undef DEF_FUNCTION_TYPE_VAR_4
+#undef DEF_FUNCTION_TYPE_VAR_5
+#undef DEF_FUNCTION_TYPE_VAR_6
+#undef DEF_FUNCTION_TYPE_VAR_7
+#undef DEF_FUNCTION_TYPE_VAR_11
+#undef DEF_POINTER_TYPE
+
+    BT_LAST,
+  };
+
+  enum Attr
+  {
+#define DEF_ATTR_NULL_TREE(ENUM) ENUM,
+#define DEF_ATTR_INT(ENUM, VALUE) ENUM,
+#define DEF_ATTR_STRING(ENUM, VALUE) ENUM,
+#define DEF_ATTR_IDENT(ENUM, STRING) ENUM,
+#define DEF_ATTR_TREE_LIST(ENUM, PURPOSE, VALUE, CHAIN) ENUM,
+
+#include "builtin-attrs.def"
+
+#undef DEF_ATTR_NULL_TREE
+#undef DEF_ATTR_INT
+#undef DEF_ATTR_STRING
+#undef DEF_ATTR_IDENT
+#undef DEF_ATTR_TREE_LIST
+
+    ATTR_LAST,
+  };
+
+  /**
+   * All builtin types, as defined in `builtin-types.def`
+   *
+   * This array is filled by the `define_builtin_types` method, during the first
+   * initialization of the `BuiltinsContext`
+   */
+  tree builtin_types[Type::BT_LAST + 1];
+
+  /**
+   * Similarly, this array contains all builtin attributes, as defined in
+   * `builtin-attr.def`
+   *
+   * This array is filled by the `define_builtin_attributes` method, during the
+   * first initialization of the `BuiltinsContext`
+   */
+  tree builtin_attributes[Attr::ATTR_LAST + 1];
+
+  void define_function_type (Type def, Type ret, bool is_variadic, size_t n,
+			     ...);
+  void define_builtin_types ();
+  void define_builtin_attributes ();
+  void define_builtins ();
+
+  void register_rust_mappings ();
+
   BuiltinsContext ();
 
   void setup_overflow_fns ();
@@ -91,20 +197,10 @@ private:
 
   void setup ();
 
-  // Define a builtin function.  BCODE is the builtin function code
-  // defined by builtins.def.  NAME is the name of the builtin function.
-  // LIBNAME is the name of the corresponding library function, and is
-  // NULL if there isn't one.  FNTYPE is the type of the function.
-  // CONST_P is true if the function has the const attribute.
-  // NORETURN_P is true if the function has the noreturn attribute.
-  void define_builtin (const std::string rust_name, built_in_function bcode,
-		       const char *name, const char *libname, tree fntype,
-		       int flags);
-
   bool lookup_gcc_builtin (const std::string &name, tree *builtin);
 
   // A mapping of the GCC built-ins exposed to GCC Rust.
-  std::map<std::string, tree> builtin_functions_;
+  std::map<std::string, tree> builtin_functions;
   std::map<std::string, std::string> rust_intrinsic_to_gcc_builtin;
 };
 
diff --git a/gcc/rust/backend/rust-compile-intrinsic.cc b/gcc/rust/backend/rust-compile-intrinsic.cc
index 977615e4cca..78eee530569 100644
--- a/gcc/rust/backend/rust-compile-intrinsic.cc
+++ b/gcc/rust/backend/rust-compile-intrinsic.cc
@@ -28,6 +28,8 @@
 #include "print-tree.h"
 #include "fold-const.h"
 #include "langhooks.h"
+#include "rust-gcc.h"
+#include "rust-constexpr.h"
 
 #include "print-tree.h"
 
@@ -199,6 +201,7 @@ Intrinsics::compile (TyTy::FnType *fntype)
 
   tree builtin = error_mark_node;
   BuiltinsContext &builtin_ctx = BuiltinsContext::get ();
+
   if (builtin_ctx.lookup_simple_builtin (fntype->get_identifier (), &builtin))
     return builtin;
 
@@ -604,7 +607,8 @@ copy_nonoverlapping_handler (Context *ctx, TyTy::FnType *fntype)
     = build2 (MULT_EXPR, size_type_node, TYPE_SIZE_UNIT (param_type), count);
 
   tree memcpy_raw = nullptr;
-  BuiltinsContext::get ().lookup_simple_builtin ("memcpy", &memcpy_raw);
+  BuiltinsContext::get ().lookup_simple_builtin ("__builtin_memcpy",
+						 &memcpy_raw);
   rust_assert (memcpy_raw);
   auto memcpy
     = build_fold_addr_expr_loc (Location ().gcc_location (), memcpy_raw);
@@ -656,18 +660,35 @@ prefetch_data_handler (Context *ctx, TyTy::FnType *fntype, Prefetch kind)
   enter_intrinsic_block (ctx, fndecl);
 
   auto addr = ctx->get_backend ()->var_expression (args[0], Location ());
-  auto locality = ctx->get_backend ()->var_expression (args[1], Location ());
+
+  // The core library technically allows you to pass any i32 value as a
+  // locality, but LLVM will then complain if the value cannot be constant
+  // evaluated. For now, we ignore the locality argument and instead always
+  // pass `3` (the most restrictive value). This allows us to still have
+  // prefetch behavior, just not as granular as expected. In future Rust
+  // versions, we hope that prefetch intrinsics will be split up according to
+  // locality, similarly to atomic intrinsics.
+  // The solution is to try and perform constant folding for the locality
+  // argument, or instead of creating a new function definition, modify the call
+  // site directly This has the bad side-effect of creating warnings about
+  // `unused name - locality`, which we hack away here:
+  // TODO: Take care of handling locality properly
+  ctx->get_backend ()->var_expression (args[1], Location ());
+
   auto rw_flag = make_unsigned_long_tree (ctx, kind == Prefetch::Write ? 1 : 0);
 
   auto prefetch_raw = NULL_TREE;
-  auto ok
-    = BuiltinsContext::get ().lookup_simple_builtin ("prefetch", &prefetch_raw);
+  auto ok = BuiltinsContext::get ().lookup_simple_builtin ("__builtin_prefetch",
+							   &prefetch_raw);
   rust_assert (ok);
   auto prefetch
     = build_fold_addr_expr_loc (Location ().gcc_location (), prefetch_raw);
 
   auto prefetch_call
-    = ctx->get_backend ()->call_expression (prefetch, {addr, rw_flag, locality},
+    = ctx->get_backend ()->call_expression (prefetch,
+					    {addr, rw_flag,
+					     // locality arg
+					     make_unsigned_long_tree (ctx, 3)},
 					    nullptr, Location ());
 
   TREE_READONLY (prefetch_call) = 0;
@@ -693,7 +714,7 @@ build_atomic_builtin_name (const std::string &prefix, Location locus,
   // TODO: Can we maybe get the generic version (atomic_store_n) to work... This
   // would be so much better
 
-  std::string result = prefix;
+  std::string result = "__" + prefix; //  + "n";
 
   auto type_name = operand_type->get_name ();
   if (type_name == "usize" || type_name == "isize")
@@ -703,6 +724,13 @@ build_atomic_builtin_name (const std::string &prefix, Location locus,
       return "";
     }
 
+  if (type_name.at (0) == 'i')
+    {
+      rust_sorry_at (locus, "atomics are not yet supported for signed "
+			    "integer types (i8, i16, i32, i64, i128)");
+      return "";
+    }
+
   auto type_size_str = allowed_types.find (type_name);
 
   if (!check_for_basic_integer_type ("atomic", locus, operand_type))
@@ -832,6 +860,7 @@ atomic_load_handler_inner (Context *ctx, TyTy::FnType *fntype, int ordering)
   TREE_SIDE_EFFECTS (load_call) = 1;
 
   ctx->add_statement (return_statement);
+
   finalize_intrinsic_block (ctx, fndecl);
 
   return fndecl;
diff --git a/gcc/rust/rust-gcc.cc b/gcc/rust/rust-gcc.cc
index e5dc6dacc76..c7253590b59 100644
--- a/gcc/rust/rust-gcc.cc
+++ b/gcc/rust/rust-gcc.cc
@@ -1456,20 +1456,20 @@ fetch_overflow_builtins (ArithmeticOrLogicalOperator op)
   switch (op)
     {
     case ArithmeticOrLogicalOperator::ADD:
-      builtin_ctx.lookup_simple_builtin ("add_overflow", &builtin);
+      builtin_ctx.lookup_simple_builtin ("__builtin_add_overflow", &builtin);
       break;
     case ArithmeticOrLogicalOperator::SUBTRACT:
-      builtin_ctx.lookup_simple_builtin ("sub_overflow", &builtin);
+      builtin_ctx.lookup_simple_builtin ("__builtin_sub_overflow", &builtin);
       break;
     case ArithmeticOrLogicalOperator::MULTIPLY:
-      builtin_ctx.lookup_simple_builtin ("mul_overflow", &builtin);
+      builtin_ctx.lookup_simple_builtin ("__builtin_mul_overflow", &builtin);
       break;
     default:
       gcc_unreachable ();
       break;
     };
 
-  builtin_ctx.lookup_simple_builtin ("abort", &abort);
+  builtin_ctx.lookup_simple_builtin ("__builtin_abort", &abort);
 
   rust_assert (abort);
   rust_assert (builtin);
diff --git a/gcc/testsuite/rust/compile/torture/intrinsics-4.rs b/gcc/testsuite/rust/compile/torture/intrinsics-4.rs
index 243d4460089..a42c5171463 100644
--- a/gcc/testsuite/rust/compile/torture/intrinsics-4.rs
+++ b/gcc/testsuite/rust/compile/torture/intrinsics-4.rs
@@ -8,7 +8,7 @@ extern "rust-intrinsic" {
 }
 
 fn main() {
-    let mut dst = 15;
+    let mut dst = 15u32;
     let new_value = 14;
 
     unsafe {
diff --git a/gcc/testsuite/rust/execute/torture/atomic_load.rs b/gcc/testsuite/rust/execute/torture/atomic_load.rs
index 28ed8ae78f1..612548be90c 100644
--- a/gcc/testsuite/rust/execute/torture/atomic_load.rs
+++ b/gcc/testsuite/rust/execute/torture/atomic_load.rs
@@ -7,14 +7,14 @@ extern "rust-intrinsic" {
     pub fn atomic_load_unordered<T: Copy>(src: *const T) -> T;
 }
 
-fn main() -> i32 {
+fn main() -> u32 {
     let one;
     let two;
     let three;
     let four;
 
     unsafe {
-        let mut src = 1;
+        let mut src = 1u32;
         one = atomic_load_seqcst(&src);
 
         src = 2;
diff --git a/gcc/testsuite/rust/execute/torture/atomic_store.rs b/gcc/testsuite/rust/execute/torture/atomic_store.rs
index 9f248b4f823..88f8a53a317 100644
--- a/gcc/testsuite/rust/execute/torture/atomic_store.rs
+++ b/gcc/testsuite/rust/execute/torture/atomic_store.rs
@@ -7,8 +7,8 @@ extern "rust-intrinsic" {
     pub fn atomic_store_unordered<T: Copy>(dst: *mut T, val: T);
 }
 
-fn main() -> i32 {
-    let mut dst = 15;
+fn main() -> u32 {
+    let mut dst = 15u32;
     let one;
     let two;
     let three;

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2022-12-01  8:12 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-12-01  8:12 [gcc/devel/rust/master] builtins: Cleanup initialization of builtins Thomas Schwinge

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).