]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
gccrs: Create LocalVariable
authorOwen Avery <powerboat9.gamer@gmail.com>
Sat, 28 Jun 2025 01:44:01 +0000 (21:44 -0400)
committerArthur Cohen <arthur.cohen@embecosm.com>
Tue, 25 Nov 2025 22:00:50 +0000 (23:00 +0100)
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 <powerboat9.gamer@gmail.com>
gcc/rust/backend/rust-compile-expr.cc
gcc/rust/rust-backend.h
gcc/rust/rust-gcc.cc
gcc/rust/rust-gcc.h

index 0a627f353524564ee3d848588986859e837d03f5..6404825b02f7f5150ab159ed2603dadeff2e873f 100644 (file)
@@ -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);
index 95ca7a9fe46dc00f8fafd2bd1432148a44205491..99496e69d5f554869cdd26afc297536d3217fc04 100644 (file)
@@ -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.
 
index 8f950d176f2958f01ffc1f9e24b4406fd54f3e6d..750c392e5928e3fdb1f2b47c88fdde0e31f7866c 100644 (file)
@@ -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.
index b3f03252700838e27ad0f778f3f1fa12885bf4d4..1ff7c5b4f2af3a9fa250e32bf62707c3a90f4723 100644 (file)
@@ -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