]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
gccrs: Create Rust::GGC::Ident
authorOwen Avery <powerboat9.gamer@gmail.com>
Tue, 24 Jun 2025 00:27:36 +0000 (20:27 -0400)
committerArthur Cohen <arthur.cohen@embecosm.com>
Tue, 5 Aug 2025 14:36:51 +0000 (16:36 +0200)
This should make it easier for us to hand identifiers off to the
back end.

gcc/rust/ChangeLog:

* Make-lang.in (GRS_OBJS): Add rust-ggc.o.
* backend/rust-compile-base.cc
(HIRCompileBase::compile_function): Adjust call to
Backend::function.
(HIRCompileBase::compile_constant_item): Likewise and adjust
initialization of Backend::typed_identifier.
* backend/rust-compile-expr.cc (CompileExpr::visit): Adjust call
to Backend::label.
* backend/rust-compile-type.cc (TyTyResolveCompile::visit):
Adjust initialization of Backend::typed_identifier.
* rust-backend.h: Add includes.
(Backend::GGC::Ident): Use Rust::GGC::Ident.
(struct typed_identifier): Store name as a GGC::Ident rather
than a std::string and adjust constructors.
(named_type): Take GGC::Ident/tl::optional<GGC::Ident> rather
than std::string.
(global_variable): Likewise.
(local_variable): Likewise.
(parameter_variable): Likewise.
(static_chain_variable): Likewise.
(label): Likewise.
(function): Likewise.
* rust-gcc.cc (named_type): Likewise.
(global_variable): Likewise.
(local_variable): Likewise.
(parameter_variable): Likewise.
(static_chain_variable): Likewise.
(label): Likewise.
(function): Likewise.
(function_defer_statement): Adjust call to Backend::label.
(get_identifier_from_string): Remove function.
(fill_in_fields): Handle adjustments to typed_identifier.
* util/rust-ggc.cc: New file.
* util/rust-ggc.h: New file.

Signed-off-by: Owen Avery <powerboat9.gamer@gmail.com>
gcc/rust/Make-lang.in
gcc/rust/backend/rust-compile-base.cc
gcc/rust/backend/rust-compile-expr.cc
gcc/rust/backend/rust-compile-type.cc
gcc/rust/rust-backend.h
gcc/rust/rust-gcc.cc
gcc/rust/util/rust-ggc.cc [new file with mode: 0644]
gcc/rust/util/rust-ggc.h [new file with mode: 0644]

index 85614b3e22466dd801ded6e82562c793266b48b2..39013d86cfc82dcef162762686c8e7e1340b69ab 100644 (file)
@@ -238,6 +238,7 @@ GRS_OBJS = \
     rust/rust-punycode.o \
     rust/rust-unwrap-segment.o \
     rust/rust-edition.o \
+    rust/rust-ggc.o \
        rust/rust-expand-format-args.o \
        rust/rust-lang-item.o \
        rust/rust-collect-lang-items.o \
index 84c4bcd3fe434b5429a5147c463c783db3929f5c..c9f9fbe76bfd6a0bba2ea2b313bd453f2e4fa9d2 100644 (file)
@@ -689,7 +689,7 @@ HIRCompileBase::compile_function (
 
   unsigned int flags = 0;
   tree fndecl = Backend::function (compiled_fn_type, ir_symbol_name,
-                                  "" /* asm_name */, flags, locus);
+                                  tl::nullopt /* asm_name */, flags, locus);
 
   setup_fndecl (fndecl, is_main_fn, fntype->has_substitutions_defined (),
                visibility, qualifiers, outer_attrs);
@@ -807,11 +807,12 @@ HIRCompileBase::compile_constant_item (
   // machineary that we already have. This means the best approach is to
   // make a _fake_ function with a block so it can hold onto temps then
   // use our constexpr code to fold it completely or error_mark_node
-  Backend::typed_identifier receiver;
+  Backend::typed_identifier receiver ("", NULL_TREE, UNKNOWN_LOCATION);
   tree compiled_fn_type = Backend::function_type (
     receiver, {}, {Backend::typed_identifier ("_", const_type, locus)}, NULL,
     locus);
-  tree fndecl = Backend::function (compiled_fn_type, ident, "", 0, locus);
+  tree fndecl
+    = Backend::function (compiled_fn_type, ident, tl::nullopt, 0, locus);
   TREE_READONLY (fndecl) = 1;
 
   tree enclosing_scope = NULL_TREE;
index 7a1e5a70ab69e7ef94ceae38a7220226ac44a3e6..3ce5961f10e18da61ae2057ddd7d2079f6e3bb91 100644 (file)
@@ -714,7 +714,8 @@ CompileExpr::visit (HIR::LoopExpr &expr)
        loop_label.get_lifetime ().get_mappings ().get_hirid (), label);
     }
 
-  tree loop_begin_label = Backend::label (fnctx.fndecl, "", expr.get_locus ());
+  tree loop_begin_label
+    = Backend::label (fnctx.fndecl, tl::nullopt, expr.get_locus ());
   tree loop_begin_label_decl
     = Backend::label_definition_statement (loop_begin_label);
   ctx->add_statement (loop_begin_label_decl);
@@ -756,7 +757,8 @@ CompileExpr::visit (HIR::WhileLoopExpr &expr)
                                    start_location, end_location);
   ctx->push_block (loop_block);
 
-  tree loop_begin_label = Backend::label (fnctx.fndecl, "", expr.get_locus ());
+  tree loop_begin_label
+    = Backend::label (fnctx.fndecl, tl::nullopt, expr.get_locus ());
   tree loop_begin_label_decl
     = Backend::label_definition_statement (loop_begin_label);
   ctx->add_statement (loop_begin_label_decl);
@@ -1143,9 +1145,8 @@ CompileExpr::visit (HIR::MatchExpr &expr)
   // setup the end label so the cases can exit properly
   tree fndecl = fnctx.fndecl;
   location_t end_label_locus = expr.get_locus (); // FIXME
-  tree end_label
-    = Backend::label (fndecl, "" /* empty creates an artificial label */,
-                     end_label_locus);
+  // tl::nullopt creates an artificial label
+  tree end_label = Backend::label (fndecl, tl::nullopt, end_label_locus);
   tree end_label_decl_statement
     = Backend::label_definition_statement (end_label);
 
index 7e56a0f4e1be6f9f52b252de30a6341902ab0a68..c397b4beb4ca1857149292e538d21f32e3bcb504 100644 (file)
@@ -189,7 +189,7 @@ TyTyResolveCompile::visit (const TyTy::ClosureType &type)
 void
 TyTyResolveCompile::visit (const TyTy::FnType &type)
 {
-  Backend::typed_identifier receiver;
+  Backend::typed_identifier receiver ("", NULL_TREE, UNKNOWN_LOCATION);
   std::vector<Backend::typed_identifier> parameters;
   std::vector<Backend::typed_identifier> results;
 
index a0df217988083ffb88fb97c19d90abd39cc3b836..2d813d91efd6b8611204b3e1a05d6beb085aa65f 100644 (file)
@@ -27,6 +27,8 @@
 #include "rust-linemap.h"
 #include "rust-diagnostics.h"
 #include "util/rust-operators.h"
+#include "util/rust-ggc.h"
+#include "util/optional.h"
 #include "tree.h"
 #include "rust-gcc.h"
 
@@ -42,21 +44,23 @@ class Bvariable;
 
 namespace Backend {
 
+namespace GGC {
+
+using Rust::GGC::Ident;
+
+} // namespace GGC
+
 void init ();
 
 // Name/type/location.  Used for function parameters, struct fields,
 // interface methods.
 struct typed_identifier
 {
-  std::string name;
+  GGC::Ident name;
   tree type;
   location_t location;
 
-  typed_identifier () : name (), type (NULL_TREE), location (UNKNOWN_LOCATION)
-  {}
-
-  typed_identifier (const std::string &a_name, tree a_type,
-                   location_t a_location)
+  typed_identifier (GGC::Ident a_name, tree a_type, location_t a_location)
     : name (a_name), type (a_type), location (a_location)
   {}
 };
@@ -133,7 +137,7 @@ tree array_type (tree element_type, tree length);
 // created via placeholder_pointer_type, placeholder_struct_type, or
 // placeholder_array_type..  (It may be called for a pointer,
 // struct, or array type in a case like "type P *byte; type Q P".)
-tree named_type (const std::string &name, tree, location_t);
+tree named_type (GGC::Ident name, tree, location_t);
 
 // Return the size of a type.
 int64_t type_size (tree);
@@ -314,8 +318,7 @@ void block_add_statements (tree, const std::vector<tree> &);
 // be put into a unique section if possible; this is intended to
 // permit the linker to garbage collect the variable if it is not
 // referenced.  LOCATION is where the variable was defined.
-Bvariable *global_variable (const std::string &name,
-                           const std::string &asm_name, tree btype,
+Bvariable *global_variable (GGC::Ident name, GGC::Ident asm_name, tree btype,
                            bool is_external, bool is_hidden,
                            bool in_unique_section, location_t location);
 
@@ -339,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, const std::string &name, tree type,
+Bvariable *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, const std::string &name,
-                              tree type, location_t location);
+Bvariable *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, const std::string &name,
-                                 tree type, location_t location);
+Bvariable *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
@@ -369,10 +372,10 @@ Bvariable *temporary_variable (tree fndecl, tree bind_tree, tree type,
 
 // Labels.
 
-// Create a new label.  NAME will be empty if this is a label
+// Create a new label.  NAME will be tl::nullopt if this is a label
 // created by the frontend for a loop construct.  The location is
 // where the label is defined.
-tree label (tree, const std::string &name, location_t);
+tree label (tree, tl::optional<GGC::Ident> name, location_t);
 
 // Create a statement which defines a label.  This statement will be
 // put into the codestream at the point where the label should be
@@ -408,12 +411,12 @@ static const unsigned int function_does_not_return = 1 << 2;
 static const unsigned int function_in_unique_section = 1 << 3;
 
 // Declare or define a function of FNTYPE.
-// NAME is the Go name of the function.  ASM_NAME, if not the empty
-// string, is the name that should be used in the symbol table; this
+// 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
 // will be non-empty if a magic extern comment is used.  FLAGS is
 // bit flags described above.
-tree function (tree fntype, const std::string &name,
-              const std::string &asm_name, unsigned int flags, location_t);
+tree function (tree fntype, GGC::Ident name, tl::optional<GGC::Ident> asm_name,
+              unsigned int flags, location_t);
 
 // Create a statement that runs all deferred calls for FUNCTION.  This should
 // be a statement that looks like this in C++:
index f440f79801b3bbd9a9170eccfe7d025b07a43ec5..42cdc6ca7f1c8f8f89a3772710a9328708d0e53a 100644 (file)
@@ -91,12 +91,6 @@ Bvariable::error_variable ()
 
 // A helper function to create a GCC identifier from a C++ string.
 
-static inline tree
-get_identifier_from_string (const std::string &str)
-{
-  return get_identifier_with_length (str.data (), str.length ());
-}
-
 namespace Backend {
 
 // Define the built-in functions that are exposed to GCCRust.
@@ -609,7 +603,7 @@ fill_in_fields (tree fill, const std::vector<typed_identifier> &fields,
   tree *pp = &field_trees;
   for (const auto &p : fields)
     {
-      tree name_tree = get_identifier_from_string (p.name);
+      tree name_tree = p.name.as_tree ();
       tree type_tree = p.type;
       if (error_operand_p (type_tree))
        return error_mark_node;
@@ -675,7 +669,7 @@ fill_in_array (tree fill, tree element_type, tree length_tree)
 // Return a named version of a type.
 
 tree
-named_type (const std::string &name, tree type, location_t location)
+named_type (GGC::Ident name, tree type, location_t location)
 {
   if (error_operand_p (type))
     return error_mark_node;
@@ -688,15 +682,14 @@ named_type (const std::string &name, tree type, location_t location)
          || TREE_CODE (type) == COMPLEX_TYPE
          || TREE_CODE (type) == BOOLEAN_TYPE))
     {
-      tree decl = build_decl (BUILTINS_LOCATION, TYPE_DECL,
-                             get_identifier_from_string (name), type);
+      tree decl
+       = build_decl (BUILTINS_LOCATION, TYPE_DECL, name.as_tree (), type);
       TYPE_NAME (type) = decl;
       return type;
     }
 
   tree copy = build_variant_type_copy (type);
-  tree decl
-    = build_decl (location, TYPE_DECL, get_identifier_from_string (name), copy);
+  tree decl = build_decl (location, TYPE_DECL, name.as_tree (), copy);
   DECL_ORIGINAL_TYPE (decl) = type;
   TYPE_NAME (copy) = decl;
   return copy;
@@ -1924,9 +1917,9 @@ convert_tree (tree type_tree, tree expr_tree, location_t location)
 // Make a global variable.
 
 Bvariable *
-global_variable (const std::string &var_name, const std::string &asm_name,
-                tree type_tree, bool is_external, bool is_hidden,
-                bool in_unique_section, location_t location)
+global_variable (GGC::Ident var_name, GGC::Ident asm_name, tree type_tree,
+                bool is_external, bool is_hidden, bool in_unique_section,
+                location_t location)
 {
   if (error_operand_p (type_tree))
     return Bvariable::error_variable ();
@@ -1936,8 +1929,7 @@ global_variable (const std::string &var_name, const std::string &asm_name,
   if ((is_external || !is_hidden) && int_size_in_bytes (type_tree) == 0)
     type_tree = non_zero_size_type (type_tree);
 
-  tree decl = build_decl (location, VAR_DECL,
-                         get_identifier_from_string (var_name), type_tree);
+  tree decl = build_decl (location, VAR_DECL, var_name.as_tree (), type_tree);
   if (is_external)
     DECL_EXTERNAL (decl) = 1;
   else
@@ -1945,11 +1937,11 @@ global_variable (const std::string &var_name, const std::string &asm_name,
   if (!is_hidden)
     {
       TREE_PUBLIC (decl) = 1;
-      SET_DECL_ASSEMBLER_NAME (decl, get_identifier_from_string (asm_name));
+      SET_DECL_ASSEMBLER_NAME (decl, asm_name.as_tree ());
     }
   else
     {
-      SET_DECL_ASSEMBLER_NAME (decl, get_identifier_from_string (asm_name));
+      SET_DECL_ASSEMBLER_NAME (decl, asm_name.as_tree ());
     }
 
   TREE_USED (decl) = 1;
@@ -1989,13 +1981,12 @@ global_variable_set_init (Bvariable *var, tree expr_tree)
 // Make a local variable.
 
 Bvariable *
-local_variable (tree function, const std::string &name, tree type_tree,
+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 ();
-  tree decl = build_decl (location, VAR_DECL, get_identifier_from_string (name),
-                         type_tree);
+  tree decl = build_decl (location, VAR_DECL, name.as_tree (), type_tree);
   DECL_CONTEXT (decl) = function;
 
   if (decl_var != NULL)
@@ -2010,13 +2001,12 @@ local_variable (tree function, const std::string &name, tree type_tree,
 // Make a function parameter variable.
 
 Bvariable *
-parameter_variable (tree function, const std::string &name, tree type_tree,
+parameter_variable (tree function, GGC::Ident name, tree type_tree,
                    location_t location)
 {
   if (error_operand_p (type_tree))
     return Bvariable::error_variable ();
-  tree decl = build_decl (location, PARM_DECL,
-                         get_identifier_from_string (name), type_tree);
+  tree decl = build_decl (location, PARM_DECL, name.as_tree (), type_tree);
   DECL_CONTEXT (decl) = function;
   DECL_ARG_TYPE (decl) = type_tree;
 
@@ -2027,13 +2017,12 @@ parameter_variable (tree function, const std::string &name, tree type_tree,
 // Make a static chain variable.
 
 Bvariable *
-static_chain_variable (tree fndecl, const std::string &name, tree type_tree,
+static_chain_variable (tree fndecl, GGC::Ident name, tree type_tree,
                       location_t location)
 {
   if (error_operand_p (type_tree))
     return Bvariable::error_variable ();
-  tree decl = build_decl (location, PARM_DECL,
-                         get_identifier_from_string (name), type_tree);
+  tree decl = build_decl (location, PARM_DECL, name.as_tree (), type_tree);
   DECL_CONTEXT (decl) = fndecl;
   DECL_ARG_TYPE (decl) = type_tree;
   TREE_USED (decl) = 1;
@@ -2124,10 +2113,10 @@ temporary_variable (tree fndecl, tree bind_tree, tree type_tree, tree init_tree,
 // Make a label.
 
 tree
-label (tree func_tree, const std::string &name, location_t location)
+label (tree func_tree, tl::optional<GGC::Ident> name, location_t location)
 {
   tree decl;
-  if (name.empty ())
+  if (!name.has_value ())
     {
       if (DECL_STRUCT_FUNCTION (func_tree) == NULL)
        push_struct_function (func_tree);
@@ -2140,7 +2129,7 @@ label (tree func_tree, const std::string &name, location_t location)
     }
   else
     {
-      tree id = get_identifier_from_string (name);
+      tree id = name->as_tree ();
       decl = build_decl (location, LABEL_DECL, id, void_type_node);
       DECL_CONTEXT (decl) = func_tree;
     }
@@ -2179,7 +2168,7 @@ label_address (tree label, location_t location)
 // Declare or define a new function.
 
 tree
-function (tree functype, const std::string &name, const std::string &asm_name,
+function (tree functype, GGC::Ident name, tl::optional<GGC::Ident> asm_name,
          unsigned int flags, location_t location)
 {
   if (error_operand_p (functype))
@@ -2187,13 +2176,13 @@ function (tree functype, const std::string &name, const std::string &asm_name,
 
   gcc_assert (FUNCTION_POINTER_TYPE_P (functype));
   functype = TREE_TYPE (functype);
-  tree id = get_identifier_from_string (name);
+  tree id = name.as_tree ();
   if (error_operand_p (id))
     return error_mark_node;
 
   tree decl = build_decl (location, FUNCTION_DECL, id, functype);
-  if (!asm_name.empty ())
-    SET_DECL_ASSEMBLER_NAME (decl, get_identifier_from_string (asm_name));
+  if (asm_name.has_value ())
+    SET_DECL_ASSEMBLER_NAME (decl, asm_name->as_tree ());
 
   if ((flags & function_is_declaration) != 0)
     DECL_EXTERNAL (decl) = 1;
@@ -2236,7 +2225,7 @@ function_defer_statement (tree function, tree undefer_tree, tree defer_tree,
     push_cfun (DECL_STRUCT_FUNCTION (function));
 
   tree stmt_list = NULL;
-  tree label = Backend::label (function, "", location);
+  tree label = Backend::label (function, tl::nullopt, location);
   tree label_def = label_definition_statement (label);
   append_to_statement_list (label_def, &stmt_list);
 
diff --git a/gcc/rust/util/rust-ggc.cc b/gcc/rust/util/rust-ggc.cc
new file mode 100644 (file)
index 0000000..0722af2
--- /dev/null
@@ -0,0 +1,41 @@
+// Copyright (C) 2025 Free Software Foundation, Inc.
+
+// This file is part of GCC.
+
+// GCC is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 3, or (at your option) any later
+// version.
+
+// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+// for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with GCC; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+#include "rust-ggc.h"
+#include "stringpool.h"
+
+namespace Rust {
+
+namespace GGC {
+
+Ident::Ident (const char *str) : inner (get_identifier (str)) {}
+
+Ident::Ident (const std::string &str)
+  : inner (get_identifier_with_length (str.c_str (), str.length ()))
+{}
+
+bool
+Ident::operator== (const std::string &other) const
+{
+  // maybe_get_identifier_with_length doesn't seem to exist
+  return maybe_get_identifier (other.c_str ()) == inner;
+}
+
+} // namespace GGC
+
+} // namespace Rust
diff --git a/gcc/rust/util/rust-ggc.h b/gcc/rust/util/rust-ggc.h
new file mode 100644 (file)
index 0000000..da28ede
--- /dev/null
@@ -0,0 +1,63 @@
+// Copyright (C) 2025 Free Software Foundation, Inc.
+
+// This file is part of GCC.
+
+// GCC is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 3, or (at your option) any later
+// version.
+
+// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+// for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with GCC; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+#ifndef RUST_GGC_H
+#define RUST_GGC_H
+
+#include "rust-system.h"
+#include "tree.h"
+
+namespace Rust {
+
+namespace GGC {
+
+class Ident
+{
+  tree inner;
+
+public:
+  Ident (const char *str);
+  Ident (const std::string &str);
+
+  bool operator== (const Ident &other) const { return inner == other.inner; }
+  bool operator== (const std::string &other) const;
+
+  const char *c_str () const { return IDENTIFIER_POINTER (inner); }
+  size_t size () const { return IDENTIFIER_LENGTH (inner); }
+
+  bool empty () const { return !size (); }
+
+  std::string as_string () const
+  {
+    return std::string (c_str (), c_str () + size ());
+  }
+
+  tree as_tree () const { return inner; }
+};
+
+static inline bool
+operator== (const std::string &a, const Ident &b)
+{
+  return b == a;
+}
+
+} // namespace GGC
+
+} // namespace Rust
+
+#endif // RUST_GGC_H