From 1ea9109809153b2d06c1d4dff7e2e9ed03d4693f Mon Sep 17 00:00:00 2001 From: Owen Avery Date: Fri, 27 Jun 2025 21:44:01 -0400 Subject: [PATCH] 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 --- 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 3ce5961f10e1..ec9ab6b8c3a0 100644 --- a/gcc/rust/backend/rust-compile-expr.cc +++ b/gcc/rust/backend/rust-compile-expr.cc @@ -171,7 +171,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); @@ -210,7 +210,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 2d813d91efd6..0d8d251ffc63 100644 --- a/gcc/rust/rust-backend.h +++ b/gcc/rust/rust-backend.h @@ -342,18 +342,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 @@ -366,9 +366,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 42cdc6ca7f1c..4cc2ed45abce 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 @@ -1980,12 +1997,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; @@ -1995,33 +2012,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; @@ -2042,12 +2059,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) @@ -2057,7 +2074,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; @@ -2107,7 +2124,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 @@ class Bvariable 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