aboutsummaryrefslogtreecommitdiff
path: root/gcc/rust
diff options
context:
space:
mode:
authorOwen Avery <powerboat9.gamer@gmail.com>2025-06-23 20:27:36 -0400
committerArthur Cohen <arthur.cohen@embecosm.com>2025-08-05 16:36:51 +0200
commitae031e3801db4750fa9441e4e7918b2fa2f90514 (patch)
treebc5b7ab1e4776d9b1de1d4a5c328838f05b8784f /gcc/rust
parent8c05bfc15372f8422203e0f78004055598fc358d (diff)
downloadgcc-ae031e3801db4750fa9441e4e7918b2fa2f90514.zip
gcc-ae031e3801db4750fa9441e4e7918b2fa2f90514.tar.gz
gcc-ae031e3801db4750fa9441e4e7918b2fa2f90514.tar.bz2
gccrs: Create Rust::GGC::Ident
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>
Diffstat (limited to 'gcc/rust')
-rw-r--r--gcc/rust/Make-lang.in1
-rw-r--r--gcc/rust/backend/rust-compile-base.cc7
-rw-r--r--gcc/rust/backend/rust-compile-expr.cc11
-rw-r--r--gcc/rust/backend/rust-compile-type.cc2
-rw-r--r--gcc/rust/rust-backend.h43
-rw-r--r--gcc/rust/rust-gcc.cc61
-rw-r--r--gcc/rust/util/rust-ggc.cc41
-rw-r--r--gcc/rust/util/rust-ggc.h63
8 files changed, 164 insertions, 65 deletions
diff --git a/gcc/rust/Make-lang.in b/gcc/rust/Make-lang.in
index 85614b3..39013d8 100644
--- a/gcc/rust/Make-lang.in
+++ b/gcc/rust/Make-lang.in
@@ -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 \
diff --git a/gcc/rust/backend/rust-compile-base.cc b/gcc/rust/backend/rust-compile-base.cc
index 84c4bcd..c9f9fbe 100644
--- a/gcc/rust/backend/rust-compile-base.cc
+++ b/gcc/rust/backend/rust-compile-base.cc
@@ -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;
diff --git a/gcc/rust/backend/rust-compile-expr.cc b/gcc/rust/backend/rust-compile-expr.cc
index 7a1e5a7..3ce5961 100644
--- a/gcc/rust/backend/rust-compile-expr.cc
+++ b/gcc/rust/backend/rust-compile-expr.cc
@@ -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);
diff --git a/gcc/rust/backend/rust-compile-type.cc b/gcc/rust/backend/rust-compile-type.cc
index 7e56a0f..c397b4b 100644
--- a/gcc/rust/backend/rust-compile-type.cc
+++ b/gcc/rust/backend/rust-compile-type.cc
@@ -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;
diff --git a/gcc/rust/rust-backend.h b/gcc/rust/rust-backend.h
index a0df217..2d813d9 100644
--- a/gcc/rust/rust-backend.h
+++ b/gcc/rust/rust-backend.h
@@ -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++:
diff --git a/gcc/rust/rust-gcc.cc b/gcc/rust/rust-gcc.cc
index f440f79..42cdc6c 100644
--- a/gcc/rust/rust-gcc.cc
+++ b/gcc/rust/rust-gcc.cc
@@ -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
index 0000000..0722af2
--- /dev/null
+++ b/gcc/rust/util/rust-ggc.cc
@@ -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
index 0000000..da28ede
--- /dev/null
+++ b/gcc/rust/util/rust-ggc.h
@@ -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