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

commit r16-5596-gb03ebbb77dd4385048ef2df808445d8312e9246f
Author: Owen Avery <[email protected]>
Date:   Fri Jun 27 21:44:01 2025 -0400

    gccrs: Create LocalVariable
    
    This should make it easier for us to move away from leaking pointers to
    Bvariable everywhere. Since LocalVariable has a single field of type
    tree, it should be the same size as a pointer to Bvariable, making the
    switch to LocalVariable wherever possible strictly an improvement.
    
    gcc/rust/ChangeLog:
    
            * backend/rust-compile-expr.cc (CompileExpr::visit): Implicitly
            convert LocalVariable to pointer to Bvariable.
            * rust-backend.h (local_variable): Return LocalVariable.
            (parameter_variable): Likewise.
            (static_chain_variable): Likewise.
            (temporary_variable): Likewise.
            * rust-gcc.cc (local_variable): Likewise.
            (parameter_variable): Likewise.
            (static_chain_variable): Likewise.
            (temporary_variable): Likewise.
            (LocalVariable::get_tree): New function.
            (LocalVariable::error_variable): Likewise.
            * rust-gcc.h (class LocalVariable): New class.
    
    Signed-off-by: Owen Avery <[email protected]>

Diff:
---
 gcc/rust/backend/rust-compile-expr.cc |  4 ++--
 gcc/rust/rust-backend.h               | 18 +++++++--------
 gcc/rust/rust-gcc.cc                  | 41 +++++++++++++++++++++++++----------
 gcc/rust/rust-gcc.h                   | 24 ++++++++++++++++++++
 4 files changed, 64 insertions(+), 23 deletions(-)

diff --git a/gcc/rust/backend/rust-compile-expr.cc 
b/gcc/rust/backend/rust-compile-expr.cc
index 0a627f353524..6404825b02f7 100644
--- a/gcc/rust/backend/rust-compile-expr.cc
+++ b/gcc/rust/backend/rust-compile-expr.cc
@@ -175,7 +175,7 @@ CompileExpr::visit (HIR::ArithmeticOrLogicalExpr &expr)
     }
 
   auto receiver_tmp = NULL_TREE;
-  auto receiver
+  Bvariable *receiver
     = Backend::temporary_variable (ctx->peek_fn ().fndecl, NULL_TREE,
                                   TREE_TYPE (lhs), lhs, true,
                                   expr.get_locus (), &receiver_tmp);
@@ -214,7 +214,7 @@ CompileExpr::visit (HIR::CompoundAssignmentExpr &expr)
   if (ctx->in_fn () && !ctx->const_context_p ())
     {
       auto tmp = NULL_TREE;
-      auto receiver
+      Bvariable *receiver
        = Backend::temporary_variable (ctx->peek_fn ().fndecl, NULL_TREE,
                                       TREE_TYPE (lhs), lhs, true,
                                       expr.get_locus (), &tmp);
diff --git a/gcc/rust/rust-backend.h b/gcc/rust/rust-backend.h
index 95ca7a9fe46d..99496e69d5f5 100644
--- a/gcc/rust/rust-backend.h
+++ b/gcc/rust/rust-backend.h
@@ -349,18 +349,18 @@ void global_variable_set_init (Bvariable *, tree);
 // the function, as otherwise the variable would be on the heap).
 // LOCATION is where the variable is defined.  For each local variable
 // the frontend will call init_statement to set the initial value.
-Bvariable *local_variable (tree function, GGC::Ident name, tree type,
-                          Bvariable *decl_var, location_t location);
+LocalVariable local_variable (tree function, GGC::Ident name, tree type,
+                             Bvariable *decl_var, location_t location);
 
 // Create a function parameter.  This is an incoming parameter, not
 // a result parameter (result parameters are treated as local
 // variables).  The arguments are as for local_variable.
-Bvariable *parameter_variable (tree function, GGC::Ident name, tree type,
-                              location_t location);
+LocalVariable parameter_variable (tree function, GGC::Ident name, tree type,
+                                 location_t location);
 
 // Create a static chain parameter.  This is the closure parameter.
-Bvariable *static_chain_variable (tree function, GGC::Ident name, tree type,
-                                 location_t location);
+LocalVariable static_chain_variable (tree function, GGC::Ident name, tree type,
+                                    location_t location);
 
 // Create a temporary variable.  A temporary variable has no name,
 // just a type.  We pass in FUNCTION and BLOCK in case they are
@@ -373,9 +373,9 @@ Bvariable *static_chain_variable (tree function, GGC::Ident 
name, tree type,
 // variable, and may not be very useful.  This function should
 // return a variable which can be referenced later and should set
 // *PSTATEMENT to a statement which initializes the variable.
-Bvariable *temporary_variable (tree fndecl, tree bind_tree, tree type,
-                              tree init, bool address_is_taken,
-                              location_t location, tree *pstatement);
+LocalVariable temporary_variable (tree fndecl, tree bind_tree, tree type,
+                                 tree init, bool address_is_taken,
+                                 location_t location, tree *pstatement);
 
 // Labels.
 
diff --git a/gcc/rust/rust-gcc.cc b/gcc/rust/rust-gcc.cc
index 8f950d176f29..750c392e5928 100644
--- a/gcc/rust/rust-gcc.cc
+++ b/gcc/rust/rust-gcc.cc
@@ -83,6 +83,23 @@ Bvariable::error_variable ()
   return new Bvariable (error_mark_node);
 }
 
+// Get the tree of a variable for use as an expression
+tree
+LocalVariable::get_tree (location_t location) const
+{
+  if (error_operand_p (t))
+    return error_mark_node;
+
+  TREE_USED (t) = 1;
+  return t;
+}
+
+LocalVariable
+LocalVariable::error_variable ()
+{
+  return LocalVariable (error_mark_node);
+}
+
 // This file implements the interface between the Rust frontend proper
 // and the gcc IR.  This implements specific instantiations of
 // abstract classes defined by the Rust frontend proper.  The Rust
@@ -2014,12 +2031,12 @@ global_variable_set_init (Bvariable *var, tree 
expr_tree)
 
 // Make a local variable.
 
-Bvariable *
+LocalVariable
 local_variable (tree function, GGC::Ident name, tree type_tree,
                Bvariable *decl_var, location_t location)
 {
   if (error_operand_p (type_tree))
-    return Bvariable::error_variable ();
+    return LocalVariable::error_variable ();
   tree decl = build_decl (location, VAR_DECL, name.as_tree (), type_tree);
   DECL_CONTEXT (decl) = function;
 
@@ -2029,33 +2046,33 @@ local_variable (tree function, GGC::Ident name, tree 
type_tree,
       SET_DECL_VALUE_EXPR (decl, decl_var->get_decl ());
     }
   rust_preserve_from_gc (decl);
-  return new Bvariable (decl);
+  return LocalVariable (decl);
 }
 
 // Make a function parameter variable.
 
-Bvariable *
+LocalVariable
 parameter_variable (tree function, GGC::Ident name, tree type_tree,
                    location_t location)
 {
   if (error_operand_p (type_tree))
-    return Bvariable::error_variable ();
+    return LocalVariable::error_variable ();
   tree decl = build_decl (location, PARM_DECL, name.as_tree (), type_tree);
   DECL_CONTEXT (decl) = function;
   DECL_ARG_TYPE (decl) = type_tree;
 
   rust_preserve_from_gc (decl);
-  return new Bvariable (decl);
+  return LocalVariable (decl);
 }
 
 // Make a static chain variable.
 
-Bvariable *
+LocalVariable
 static_chain_variable (tree fndecl, GGC::Ident name, tree type_tree,
                       location_t location)
 {
   if (error_operand_p (type_tree))
-    return Bvariable::error_variable ();
+    return LocalVariable::error_variable ();
   tree decl = build_decl (location, PARM_DECL, name.as_tree (), type_tree);
   DECL_CONTEXT (decl) = fndecl;
   DECL_ARG_TYPE (decl) = type_tree;
@@ -2076,12 +2093,12 @@ static_chain_variable (tree fndecl, GGC::Ident name, 
tree type_tree,
   DECL_STATIC_CHAIN (fndecl) = 1;
 
   rust_preserve_from_gc (decl);
-  return new Bvariable (decl);
+  return LocalVariable (decl);
 }
 
 // Make a temporary variable.
 
-Bvariable *
+LocalVariable
 temporary_variable (tree fndecl, tree bind_tree, tree type_tree, tree 
init_tree,
                    bool is_address_taken, location_t location,
                    tree *pstatement)
@@ -2091,7 +2108,7 @@ temporary_variable (tree fndecl, tree bind_tree, tree 
type_tree, tree init_tree,
       || error_operand_p (fndecl))
     {
       *pstatement = error_mark_node;
-      return Bvariable::error_variable ();
+      return LocalVariable::error_variable ();
     }
 
   tree var;
@@ -2141,7 +2158,7 @@ temporary_variable (tree fndecl, tree bind_tree, tree 
type_tree, tree init_tree,
          || TREE_TYPE (init_tree) == void_type_node))
     *pstatement = compound_statement (init_tree, *pstatement);
 
-  return new Bvariable (var);
+  return LocalVariable (var);
 }
 
 // Make a label.
diff --git a/gcc/rust/rust-gcc.h b/gcc/rust/rust-gcc.h
index b3f032527008..1ff7c5b4f2af 100644
--- a/gcc/rust/rust-gcc.h
+++ b/gcc/rust/rust-gcc.h
@@ -59,4 +59,28 @@ private:
   tree orig_type_;
 };
 
+// like Bvariable, but orig_type_ == nullptr always holds
+// could be any variable which isn't a zero-sized global
+class LocalVariable
+{
+public:
+  LocalVariable (tree t) : t (t) {}
+
+  // Get the tree for use as an expression.
+  tree get_tree (location_t) const;
+
+  // Get the actual decl;
+  tree get_decl () const { return t; }
+
+  // Create an error variable.  This is used for cases which should
+  // not occur in a correct program, in order to keep the compilation
+  // going without crashing.
+  static LocalVariable error_variable ();
+
+  operator Bvariable * () const { return new Bvariable (t); }
+
+private:
+  tree t;
+};
+
 #endif // RUST_GCC

Reply via email to