From: Elle Rhumsaa <[email protected]>

Adds a `flags` argument to the `compile_intrinsic_function` argument to
avoid modifying the `tree` for the function declaration after it has
been created.

gcc/
        * rust/backend/rust-intrinsic-handlers.cc: add flags to the
        `compile_intrinsic_function` declaration, and calls to the
        function
        * rust/backend/rust-backend.h: add function flag definitions
        * rust/rust-gcc.cc: add macro calls based on flags
---
 gcc/rust/backend/rust-intrinsic-handlers.cc | 127 ++++++++++----------
 gcc/rust/rust-backend.h                     |  33 +++++
 gcc/rust/rust-gcc.cc                        |  20 +++
 3 files changed, 117 insertions(+), 63 deletions(-)

diff --git a/gcc/rust/backend/rust-intrinsic-handlers.cc 
b/gcc/rust/backend/rust-intrinsic-handlers.cc
index abec54c4ad7a..6c082d1f4933 100644
--- a/gcc/rust/backend/rust-intrinsic-handlers.cc
+++ b/gcc/rust/backend/rust-intrinsic-handlers.cc
@@ -112,7 +112,8 @@ check_for_cached_intrinsic (Context *ctx, TyTy::FnType 
*fntype, tree *lookup)
 }
 
 static tree
-compile_intrinsic_function (Context *ctx, TyTy::FnType *fntype)
+compile_intrinsic_function (Context *ctx, TyTy::FnType *fntype,
+                           unsigned int flags)
 {
   maybe_override_ctx (fntype);
 
@@ -123,16 +124,9 @@ compile_intrinsic_function (Context *ctx, TyTy::FnType 
*fntype)
     = canonical_path.get () + fntype->subst_as_string ();
   std::string asm_name = ctx->mangle_item (fntype, canonical_path);
 
-  unsigned int flags = 0;
   tree fndecl = Backend::function (compiled_fn_type, ir_symbol_name, asm_name,
                                   flags, fntype->get_ident ().locus);
 
-  TREE_PUBLIC (fndecl) = 0;
-  TREE_READONLY (fndecl) = 1;
-  DECL_ARTIFICIAL (fndecl) = 1;
-  DECL_EXTERNAL (fndecl) = 0;
-  DECL_DECLARED_INLINE_P (fndecl) = 1;
-
   return fndecl;
 }
 
@@ -242,7 +236,9 @@ unchecked_op (Context *ctx, TyTy::FnType *fntype, tree_code 
op)
   if (check_for_cached_intrinsic (ctx, fntype, &lookup))
     return lookup;
 
-  auto fndecl = compile_intrinsic_function (ctx, fntype);
+  auto fndecl
+    = compile_intrinsic_function (ctx, fntype,
+                                 Backend::function_intrinsic_default);
 
   // setup the params
   std::vector<Bvariable *> param_vars;
@@ -287,7 +283,9 @@ expect (Context *ctx, TyTy::FnType *fntype, bool likely)
   if (check_for_cached_intrinsic (ctx, fntype, &lookup))
     return lookup;
 
-  auto fndecl = compile_intrinsic_function (ctx, fntype);
+  auto fndecl
+    = compile_intrinsic_function (ctx, fntype,
+                                 Backend::function_intrinsic_default);
 
   enter_intrinsic_block (ctx, fndecl);
 
@@ -331,16 +329,13 @@ try_handler (Context *ctx, TyTy::FnType *fntype, bool 
is_new_api)
   tree lookup = NULL_TREE;
   if (check_for_cached_intrinsic (ctx, fntype, &lookup))
     return lookup;
-  auto fndecl = compile_intrinsic_function (ctx, fntype);
-
-  enter_intrinsic_block (ctx, fndecl);
-
   // The following tricks are needed to make sure the try-catch blocks are not
   // optimized away
-  TREE_READONLY (fndecl) = 0;
-  DECL_DISREGARD_INLINE_LIMITS (fndecl) = 1;
-  DECL_ATTRIBUTES (fndecl) = tree_cons (get_identifier ("always_inline"),
-                                       NULL_TREE, DECL_ATTRIBUTES (fndecl));
+  auto fndecl
+    = compile_intrinsic_function (ctx, fntype,
+                                 Backend::function_intrinsic_always_inline);
+
+  enter_intrinsic_block (ctx, fndecl);
 
   // BUILTIN try_handler FN BODY BEGIN
   // setup the params
@@ -431,7 +426,9 @@ wrapping_op (Context *ctx, TyTy::FnType *fntype, tree_code 
op)
   if (check_for_cached_intrinsic (ctx, fntype, &lookup))
     return lookup;
 
-  auto fndecl = compile_intrinsic_function (ctx, fntype);
+  auto fndecl
+    = compile_intrinsic_function (ctx, fntype,
+                                 Backend::function_intrinsic_default);
 
   // setup the params
   std::vector<Bvariable *> param_vars;
@@ -478,7 +475,9 @@ op_with_overflow (Context *ctx, TyTy::FnType *fntype, 
tree_code op)
   if (check_for_cached_intrinsic (ctx, fntype, &lookup))
     return lookup;
 
-  auto fndecl = compile_intrinsic_function (ctx, fntype);
+  auto fndecl
+    = compile_intrinsic_function (ctx, fntype,
+                                 Backend::function_intrinsic_default);
 
   // setup the params
   std::vector<Bvariable *> param_vars;
@@ -581,11 +580,9 @@ copy (Context *ctx, TyTy::FnType *fntype, bool overlaps)
   if (check_for_cached_intrinsic (ctx, fntype, &lookup))
     return lookup;
 
-  auto fndecl = compile_intrinsic_function (ctx, fntype);
-
   // Most intrinsic functions are pure - not `copy_nonoverlapping` and `copy`
-  TREE_READONLY (fndecl) = 0;
-  TREE_SIDE_EFFECTS (fndecl) = 1;
+  auto fndecl = compile_intrinsic_function (
+    ctx, fntype, Backend::function_intrinsic_with_side_effects);
 
   // setup the params
   std::vector<Bvariable *> param_vars;
@@ -642,11 +639,9 @@ atomic_store (Context *ctx, TyTy::FnType *fntype, memmodel 
model)
   if (check_for_cached_intrinsic (ctx, fntype, &lookup))
     return lookup;
 
-  auto fndecl = compile_intrinsic_function (ctx, fntype);
-
   // Most intrinsic functions are pure but not the atomic ones
-  TREE_READONLY (fndecl) = 0;
-  TREE_SIDE_EFFECTS (fndecl) = 1;
+  auto fndecl = compile_intrinsic_function (
+    ctx, fntype, Backend::function_intrinsic_with_side_effects);
 
   // setup the params
   std::vector<Bvariable *> param_vars;
@@ -703,12 +698,11 @@ atomic_load (Context *ctx, TyTy::FnType *fntype, memmodel 
model)
   if (check_for_cached_intrinsic (ctx, fntype, &lookup))
     return lookup;
 
-  auto fndecl = compile_intrinsic_function (ctx, fntype);
-
   // Most intrinsic functions are pure but not the atomic ones
   // FIXME: Is atomic_load_* pure? Feels like it shouldn't so
-  TREE_READONLY (fndecl) = 0;
-  TREE_SIDE_EFFECTS (fndecl) = 1;
+  //   Probably not, since it involves an implicit memory barrier
+  auto fndecl = compile_intrinsic_function (
+    ctx, fntype, Backend::function_intrinsic_with_side_effects);
 
   // setup the params
   std::vector<Bvariable *> param_vars;
@@ -765,11 +759,9 @@ atomic_exchange (Context *ctx, TyTy::FnType *fntype, 
memmodel model)
   if (check_for_cached_intrinsic (ctx, fntype, &lookup))
     return lookup;
 
-  auto fndecl = compile_intrinsic_function (ctx, fntype);
-
   // Most intrinsic functions are pure but not the atomic ones
-  TREE_READONLY (fndecl) = 0;
-  TREE_SIDE_EFFECTS (fndecl) = 1;
+  auto fndecl = compile_intrinsic_function (
+    ctx, fntype, Backend::function_intrinsic_with_side_effects);
 
   // setup the params
   std::vector<Bvariable *> param_vars;
@@ -837,7 +829,9 @@ ctlz_handler (Context *ctx, TyTy::FnType *fntype, bool 
nonzero)
   if (check_for_cached_intrinsic (ctx, fntype, &lookup))
     return lookup;
 
-  auto fndecl = compile_intrinsic_function (ctx, fntype);
+  auto fndecl
+    = compile_intrinsic_function (ctx, fntype,
+                                 Backend::function_intrinsic_default);
 
   std::vector<Bvariable *> param_vars;
   compile_fn_params (ctx, fntype, fndecl, &param_vars);
@@ -982,7 +976,9 @@ cttz_handler (Context *ctx, TyTy::FnType *fntype, bool 
nonzero)
   if (check_for_cached_intrinsic (ctx, fntype, &lookup))
     return lookup;
 
-  auto fndecl = compile_intrinsic_function (ctx, fntype);
+  auto fndecl
+    = compile_intrinsic_function (ctx, fntype,
+                                 Backend::function_intrinsic_default);
 
   std::vector<Bvariable *> param_vars;
   compile_fn_params (ctx, fntype, fndecl, &param_vars);
@@ -1203,13 +1199,10 @@ assume (Context *ctx, TyTy::FnType *fntype)
   if (check_for_cached_intrinsic (ctx, fntype, &lookup))
     return lookup;
 
-  auto fndecl = compile_intrinsic_function (ctx, fntype);
-
   // TODO: make sure these are necessary
-  TREE_READONLY (fndecl) = 0;
-  DECL_DISREGARD_INLINE_LIMITS (fndecl) = 1;
-  DECL_ATTRIBUTES (fndecl) = tree_cons (get_identifier ("always_inline"),
-                                       NULL_TREE, DECL_ATTRIBUTES (fndecl));
+  auto fndecl
+    = compile_intrinsic_function (ctx, fntype,
+                                 Backend::function_intrinsic_always_inline);
 
   std::vector<Bvariable *> param_vars;
   compile_fn_params (ctx, fntype, fndecl, &param_vars);
@@ -1268,7 +1261,9 @@ discriminant_value (Context *ctx, TyTy::FnType *fntype)
   if (check_for_cached_intrinsic (ctx, fntype, &lookup))
     return lookup;
 
-  auto fndecl = compile_intrinsic_function (ctx, fntype);
+  auto fndecl
+    = compile_intrinsic_function (ctx, fntype,
+                                 Backend::function_intrinsic_default);
 
   std::vector<Bvariable *> param_vars;
   compile_fn_params (ctx, fntype, fndecl, &param_vars);
@@ -1320,7 +1315,9 @@ variant_count (Context *ctx, TyTy::FnType *fntype)
   if (check_for_cached_intrinsic (ctx, fntype, &lookup))
     return lookup;
 
-  auto fndecl = compile_intrinsic_function (ctx, fntype);
+  auto fndecl
+    = compile_intrinsic_function (ctx, fntype,
+                                 Backend::function_intrinsic_default);
 
   std::vector<Bvariable *> param_vars;
   compile_fn_params (ctx, fntype, fndecl, &param_vars);
@@ -1359,11 +1356,9 @@ move_val_init (Context *ctx, TyTy::FnType *fntype)
   if (check_for_cached_intrinsic (ctx, fntype, &lookup))
     return lookup;
 
-  auto fndecl = compile_intrinsic_function (ctx, fntype);
-
   // Most intrinsic functions are pure - not `move_val_init`
-  TREE_READONLY (fndecl) = 0;
-  TREE_SIDE_EFFECTS (fndecl) = 1;
+  auto fndecl = compile_intrinsic_function (
+    ctx, fntype, Backend::function_intrinsic_with_side_effects);
 
   // get the template parameter type tree fn size_of<T>();
   rust_assert (fntype->get_num_substitutions () == 1);
@@ -1414,11 +1409,9 @@ uninit (Context *ctx, TyTy::FnType *fntype)
   if (check_for_cached_intrinsic (ctx, fntype, &lookup))
     return lookup;
 
-  auto fndecl = compile_intrinsic_function (ctx, fntype);
-
   // Most intrinsic functions are pure - not `uninit_handler`
-  TREE_READONLY (fndecl) = 0;
-  TREE_SIDE_EFFECTS (fndecl) = 1;
+  auto fndecl = compile_intrinsic_function (
+    ctx, fntype, Backend::function_intrinsic_with_side_effects);
 
   // get the template parameter type tree fn uninit<T>();
   rust_assert (fntype->get_num_substitutions () == 1);
@@ -1490,11 +1483,9 @@ prefetch_data (Context *ctx, TyTy::FnType *fntype, 
Prefetch kind)
   if (check_for_cached_intrinsic (ctx, fntype, &lookup))
     return lookup;
 
-  auto fndecl = compile_intrinsic_function (ctx, fntype);
-
   // prefetching isn't pure and shouldn't be discarded after GIMPLE
-  TREE_READONLY (fndecl) = 0;
-  TREE_SIDE_EFFECTS (fndecl) = 1;
+  auto fndecl = compile_intrinsic_function (
+    ctx, fntype, Backend::function_intrinsic_with_side_effects);
 
   std::vector<Bvariable *> args;
   compile_fn_params (ctx, fntype, fndecl, &args);
@@ -1554,7 +1545,9 @@ rotate (Context *ctx, TyTy::FnType *fntype, tree_code op)
   if (check_for_cached_intrinsic (ctx, fntype, &lookup))
     return lookup;
 
-  auto fndecl = compile_intrinsic_function (ctx, fntype);
+  auto fndecl
+    = compile_intrinsic_function (ctx, fntype,
+                                 Backend::function_intrinsic_default);
 
   // setup the params
   std::vector<Bvariable *> param_vars;
@@ -1593,7 +1586,9 @@ transmute (Context *ctx, TyTy::FnType *fntype)
   if (check_for_cached_intrinsic (ctx, fntype, &lookup))
     return lookup;
 
-  auto fndecl = compile_intrinsic_function (ctx, fntype);
+  auto fndecl
+    = compile_intrinsic_function (ctx, fntype,
+                                 Backend::function_intrinsic_default);
 
   std::vector<Bvariable *> param_vars;
   std::vector<tree_node *> compiled_types;
@@ -1667,7 +1662,9 @@ sizeof_handler (Context *ctx, TyTy::FnType *fntype)
   if (check_for_cached_intrinsic (ctx, fntype, &lookup))
     return lookup;
 
-  auto fndecl = compile_intrinsic_function (ctx, fntype);
+  auto fndecl
+    = compile_intrinsic_function (ctx, fntype,
+                                 Backend::function_intrinsic_default);
 
   // get the template parameter type tree fn size_of<T>();
   rust_assert (fntype->get_num_substitutions () == 1);
@@ -1697,7 +1694,9 @@ offset (Context *ctx, TyTy::FnType *fntype)
   // offset intrinsic has two params dst pointer and offset isize
   rust_assert (fntype->get_params ().size () == 2);
 
-  auto fndecl = compile_intrinsic_function (ctx, fntype);
+  auto fndecl
+    = compile_intrinsic_function (ctx, fntype,
+                                 Backend::function_intrinsic_default);
 
   std::vector<Bvariable *> param_vars;
   compile_fn_params (ctx, fntype, fndecl, &param_vars);
@@ -1737,7 +1736,9 @@ bswap_handler (Context *ctx, TyTy::FnType *fntype)
   if (check_for_cached_intrinsic (ctx, fntype, &lookup))
     return lookup;
 
-  auto fndecl = compile_intrinsic_function (ctx, fntype);
+  auto fndecl
+    = compile_intrinsic_function (ctx, fntype,
+                                 Backend::function_intrinsic_default);
 
   auto locus = fntype->get_locus ();
 
diff --git a/gcc/rust/rust-backend.h b/gcc/rust/rust-backend.h
index ecd86836262b..2f11677984ed 100644
--- a/gcc/rust/rust-backend.h
+++ b/gcc/rust/rust-backend.h
@@ -423,6 +423,39 @@ static const unsigned int function_does_not_return = 1 << 
2;
 // possible.  This is used for field tracking.
 static const unsigned int function_in_unique_section = 1 << 3;
 
+// Set if the function should be inlined.
+// Incompatible with `function_is_uninlinable`.
+static const unsigned int function_is_inline = 1 << 4;
+
+// Set if the function should be inlined.
+// Incompatible with `function_is_uninlinable`.
+static const unsigned int function_always_inline = 1 << 5;
+
+// Set if the function represents a compiler-generated entity.
+static const unsigned int function_is_artificial = 1 << 6;
+
+// Set if the function has public visibility.
+static const unsigned int function_is_public = 1 << 7;
+
+// Set if the function only accesses memory with read-only operations.
+static const unsigned int function_is_readonly = 1 << 8;
+
+// Set if the function has side-effects.
+// For example, creating an implicit memory barrier.
+static const unsigned int function_has_side_effects = 1 << 9;
+
+// Set default flags for intrinsic functions.
+static const unsigned int function_intrinsic_default
+  = function_is_readonly | function_is_artificial | function_is_inline;
+
+// Set default flags for an intrinsic function with side effects.
+static const unsigned int function_intrinsic_with_side_effects
+  = function_is_artificial | function_is_inline | function_has_side_effects;
+
+// Set default flags for an intrinsic function that should always be inlined.
+static const unsigned int function_intrinsic_always_inline
+  = function_is_artificial | function_is_inline | function_always_inline;
+
 // Declare or define a function of FNTYPE.
 // NAME is the Go name of the function.  ASM_NAME, if not tl::nullopt,
 // is the name that should be used in the symbol table; this
diff --git a/gcc/rust/rust-gcc.cc b/gcc/rust/rust-gcc.cc
index ab02bcd556a0..bf83583f2867 100644
--- a/gcc/rust/rust-gcc.cc
+++ b/gcc/rust/rust-gcc.cc
@@ -2252,6 +2252,26 @@ function (tree functype, GGC::Ident name, 
tl::optional<GGC::Ident> asm_name,
     TREE_THIS_VOLATILE (decl) = 1;
   if ((flags & function_in_unique_section) != 0)
     resolve_unique_section (decl, 0, 1);
+  if ((flags & function_is_public) != 0)
+    TREE_PUBLIC (decl) = 1;
+  else
+    TREE_PUBLIC (decl) = 0;
+  if ((flags & function_is_readonly) != 0)
+    TREE_READONLY (decl) = 1;
+  else
+    TREE_READONLY (decl) = 0;
+  if ((flags & function_has_side_effects) != 0)
+    TREE_SIDE_EFFECTS (decl) = 1;
+  if ((flags & function_is_inline) != 0
+      && (flags & function_is_uninlinable) == 0)
+    DECL_DECLARED_INLINE_P (decl) = 1;
+  if ((flags & function_always_inline) != 0
+      && (flags & function_is_uninlinable) == 0)
+    {
+      DECL_DISREGARD_INLINE_LIMITS (decl) = 1;
+      DECL_ATTRIBUTES (decl) = tree_cons (get_identifier ("always_inline"),
+                                         NULL_TREE, DECL_ATTRIBUTES (decl));
+    }
 
   rust_preserve_from_gc (decl);
   return decl;
-- 
2.54.0

Reply via email to