[gcc r14-7553] gccrs: builtin: Cleanup handling of builtin macros

Arthur Cohen cohenarthur@gcc.gnu.org
Tue Jan 16 17:43:56 GMT 2024


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

commit r14-7553-gcf1287ee24c5c83b38737c50e3cd37ab62f3d279
Author: Arthur Cohen <arthur.cohen@embecosm.com>
Date:   Wed May 3 11:19:30 2023 +0200

    gccrs: builtin: Cleanup handling of builtin macros
    
    This commit regroups information related to builtin macros in one place instead
    of spreading it over multiple files. It also adds a simple bi-directional
    hashmap in order to perform lookups from a key as well as a value.
    
    gcc/rust/ChangeLog:
    
            * ast/rust-macro.cc (builtin_macro_from_string): Move function.
            * ast/rust-macro.h (enum class): Move enum.
            (builtin_macro_from_string): Move function.
            * expand/rust-macro-builtins.cc (builtin_macro_from_string): New function.
            (make_macro_path_str): Use new bi-map.
            (parse_single_string_literal): Use new `BuiltinMacro` enum.
            (MacroBuiltin::include_bytes_handler): Likewise.
            (MacroBuiltin::include_str_handler): Likewise.
            (MacroBuiltin::compile_error_handler): Likewise.
            (MacroBuiltin::concat_handler): Likewise.
            (MacroBuiltin::env_handler): Likewise.
            (MacroBuiltin::include_handler): Likewise.
            (MacroBuiltin::sorry): New function.
            * expand/rust-macro-builtins.h (enum class): Move enum here.
            (builtin_macro_from_string): New function declaration.
            * resolve/rust-early-name-resolver.cc (EarlyNameResolver::visit): Use
            new function.
            * util/rust-hir-map.cc (Mappings::insert_macro_def): Remove old
            builtin macro map.

Diff:
---
 gcc/rust/ast/rust-macro.cc                   |  42 --------
 gcc/rust/ast/rust-macro.h                    |  23 +---
 gcc/rust/expand/rust-macro-builtins.cc       | 153 +++++++++++++++++----------
 gcc/rust/expand/rust-macro-builtins.h        |  64 ++++++++++-
 gcc/rust/resolve/rust-early-name-resolver.cc |   3 +-
 gcc/rust/util/rust-hir-map.cc                |  22 +---
 6 files changed, 167 insertions(+), 140 deletions(-)

diff --git a/gcc/rust/ast/rust-macro.cc b/gcc/rust/ast/rust-macro.cc
index b558969eba4..f36feda9970 100644
--- a/gcc/rust/ast/rust-macro.cc
+++ b/gcc/rust/ast/rust-macro.cc
@@ -21,47 +21,5 @@
 namespace Rust {
 namespace AST {
 
-BuiltinMacro
-builtin_macro_from_string (const std::string &identifier)
-{
-  if (identifier == "assert")
-    return BuiltinMacro::Assert;
-
-  if (identifier == "file")
-    return BuiltinMacro::File;
-
-  if (identifier == "line")
-    return BuiltinMacro::Line;
-
-  if (identifier == "column")
-    return BuiltinMacro::Column;
-
-  if (identifier == "include_bytes")
-    return BuiltinMacro::IncludeBytes;
-
-  if (identifier == "include_str")
-    return BuiltinMacro::IncludeStr;
-
-  if (identifier == "stringify")
-    return BuiltinMacro::Stringify;
-
-  if (identifier == "compile_error")
-    return BuiltinMacro::CompileError;
-
-  if (identifier == "concat")
-    return BuiltinMacro::Concat;
-
-  if (identifier == "env")
-    return BuiltinMacro::Env;
-
-  if (identifier == "cfg")
-    return BuiltinMacro::Cfg;
-
-  if (identifier == "include")
-    return BuiltinMacro::Include;
-
-  gcc_unreachable ();
-}
-
 } // namespace AST
 } // namespace Rust
diff --git a/gcc/rust/ast/rust-macro.h b/gcc/rust/ast/rust-macro.h
index 7216db8be53..b6349a71ed3 100644
--- a/gcc/rust/ast/rust-macro.h
+++ b/gcc/rust/ast/rust-macro.h
@@ -25,6 +25,7 @@
 #include "rust-location.h"
 #include "rust-item.h"
 #include "rust-make-unique.h"
+#include "rust-macro-builtins.h"
 
 namespace Rust {
 namespace AST {
@@ -578,28 +579,6 @@ protected:
   }
 };
 
-/**
- * All builtin macros possible
- */
-enum class BuiltinMacro
-{
-  Assert,
-  File,
-  Line,
-  Column,
-  IncludeBytes,
-  IncludeStr,
-  Stringify,
-  CompileError,
-  Concat,
-  Env,
-  Cfg,
-  Include
-};
-
-BuiltinMacro
-builtin_macro_from_string (const std::string &identifier);
-
 /* AST node of a macro invocation, which is replaced by the macro result at
  * compile time. This is technically a sum-type/tagged-union, which represents
  * both classic macro invocations and builtin macro invocations. Regular macro
diff --git a/gcc/rust/expand/rust-macro-builtins.cc b/gcc/rust/expand/rust-macro-builtins.cc
index 29a8b8b867b..f0f1f8c9230 100644
--- a/gcc/rust/expand/rust-macro-builtins.cc
+++ b/gcc/rust/expand/rust-macro-builtins.cc
@@ -32,54 +32,91 @@
 #include "bi-map.h"
 
 namespace Rust {
+static const BiMap<std::string, BuiltinMacro> builtins = {{
+  {"assert", BuiltinMacro::Assert},
+  {"file", BuiltinMacro::File},
+  {"line", BuiltinMacro::Line},
+  {"column", BuiltinMacro::Column},
+  {"include_bytes", BuiltinMacro::IncludeBytes},
+  {"include_str", BuiltinMacro::IncludeStr},
+  {"stringify", BuiltinMacro::Stringify},
+  {"compile_error", BuiltinMacro::CompileError},
+  {"concat", BuiltinMacro::Concat},
+  {"env", BuiltinMacro::Env},
+  {"option_env", BuiltinMacro::OptionEnv},
+  {"cfg", BuiltinMacro::Cfg},
+  {"include", BuiltinMacro::Include},
+  {"format_args", BuiltinMacro::FormatArgs},
+  {"format_args_nl", BuiltinMacro::FormatArgsNl},
+  {"concat_idents", BuiltinMacro::ConcatIdents},
+  {"module_path", BuiltinMacro::ModulePath},
+  {"asm", BuiltinMacro::Asm},
+  {"llvm_asm", BuiltinMacro::LlvmAsm},
+  {"global_asm", BuiltinMacro::GlobalAsm},
+  {"log_syntax", BuiltinMacro::LogSyntax},
+  {"trace_macros", BuiltinMacro::TraceMacros},
+  {"test", BuiltinMacro::Test},
+  {"bench", BuiltinMacro::Bench},
+  {"test_case", BuiltinMacro::TestCase},
+  {"global_allocator", BuiltinMacro::GlobalAllocator},
+  {"cfg_accessible", BuiltinMacro::CfgAccessible},
+  {"RustcEncodable", BuiltinMacro::RustcDecodable},
+  {"RustcDecodable", BuiltinMacro::RustcEncodable},
+}};
+
+std::unordered_map<
+  std::string, std::function<AST::Fragment (Location, AST::MacroInvocData &)>>
+  MacroBuiltin::builtin_transcribers = {
+    {"assert", MacroBuiltin::assert_handler},
+    {"file", MacroBuiltin::file_handler},
+    {"line", MacroBuiltin::line_handler},
+    {"column", MacroBuiltin::column_handler},
+    {"include_bytes", MacroBuiltin::include_bytes_handler},
+    {"include_str", MacroBuiltin::include_str_handler},
+    {"stringify", MacroBuiltin::stringify_handler},
+    {"compile_error", MacroBuiltin::compile_error_handler},
+    {"concat", MacroBuiltin::concat_handler},
+    {"env", MacroBuiltin::env_handler},
+    {"cfg", MacroBuiltin::cfg_handler},
+    {"include", MacroBuiltin::include_handler},
+    /* Unimplemented macro builtins */
+    {"format_args", MacroBuiltin::sorry},
+    {"option_env", MacroBuiltin::sorry},
+    {"format_args_nl", MacroBuiltin::sorry},
+    {"concat_idents", MacroBuiltin::sorry},
+    {"module_path", MacroBuiltin::sorry},
+    {"asm", MacroBuiltin::sorry},
+    {"llvm_asm", MacroBuiltin::sorry},
+    {"global_asm", MacroBuiltin::sorry},
+    {"log_syntax", MacroBuiltin::sorry},
+    {"trace_macros", MacroBuiltin::sorry},
+    {"test", MacroBuiltin::sorry},
+    {"bench", MacroBuiltin::sorry},
+    {"test_case", MacroBuiltin::sorry},
+    {"global_allocator", MacroBuiltin::sorry},
+    {"cfg_accessible", MacroBuiltin::sorry},
+    {"RustcEncodable", MacroBuiltin::sorry},
+    {"RustcDecodable", MacroBuiltin::sorry},
+};
+
+// FIXME: This should return an Optional
+BuiltinMacro
+builtin_macro_from_string (const std::string &identifier)
+{
+  auto macro = builtins.lookup (identifier);
+  rust_assert (builtins.is_iter_ok (macro));
+
+  return macro->second;
+}
+
 namespace {
 std::string
-make_macro_path_str (AST::BuiltinMacro kind)
+make_macro_path_str (BuiltinMacro kind)
 {
-  std::string path_str;
+  auto str = builtins.lookup (kind);
+  rust_assert (builtins.is_iter_ok (str));
 
-  switch (kind)
-    {
-    // TODO: Should this be a table lookup?
-    case AST::BuiltinMacro::Assert:
-      path_str = "assert";
-      break;
-    case AST::BuiltinMacro::File:
-      path_str = "file";
-      break;
-    case AST::BuiltinMacro::Line:
-      path_str = "line";
-      break;
-    case AST::BuiltinMacro::Column:
-      path_str = "column";
-      break;
-    case AST::BuiltinMacro::IncludeBytes:
-      path_str = "include_bytes";
-      break;
-    case AST::BuiltinMacro::IncludeStr:
-      path_str = "include_str";
-      break;
-    case AST::BuiltinMacro::Stringify:
-      path_str = "stringify";
-      break;
-    case AST::BuiltinMacro::CompileError:
-      path_str = "compile_error";
-      break;
-    case AST::BuiltinMacro::Concat:
-      path_str = "concat";
-      break;
-    case AST::BuiltinMacro::Env:
-      path_str = "env";
-      break;
-    case AST::BuiltinMacro::Cfg:
-      path_str = "cfg";
-      break;
-    case AST::BuiltinMacro::Include:
-      path_str = "include";
-      break;
-    }
-
-  return path_str;
+  return str->second;
 }
 
 static std::vector<std::unique_ptr<AST::MacroInvocation>>
@@ -116,7 +153,7 @@ make_string (Location locus, std::string value)
 // TODO: Is this correct?
 static AST::Fragment
 make_eager_builtin_invocation (
-  AST::BuiltinMacro kind, Location locus, AST::DelimTokenTree arguments,
+  BuiltinMacro kind, Location locus, AST::DelimTokenTree arguments,
   std::vector<std::unique_ptr<AST::MacroInvocation>> &&pending_invocations)
 {
   auto path_str = make_macro_path_str (kind);
@@ -224,7 +261,7 @@ try_expand_many_expr (Parser<MacroInvocLexer> &parser,
    but otherwise enforce that these are the only tokens.  */
 
 std::unique_ptr<AST::Expr>
-parse_single_string_literal (AST::BuiltinMacro kind,
+parse_single_string_literal (BuiltinMacro kind,
 			     AST::DelimTokenTree &invoc_token_tree,
 			     Location invoc_locus, MacroExpander *expander)
 {
@@ -384,7 +421,7 @@ MacroBuiltin::include_bytes_handler (Location invoc_locus,
   /* Get target filename from the macro invocation, which is treated as a path
      relative to the include!-ing file (currently being compiled).  */
   auto lit_expr
-    = parse_single_string_literal (AST::BuiltinMacro::IncludeBytes,
+    = parse_single_string_literal (BuiltinMacro::IncludeBytes,
 				   invoc.get_delim_tok_tree (), invoc_locus,
 				   invoc.get_expander ());
   if (lit_expr == nullptr)
@@ -444,7 +481,7 @@ MacroBuiltin::include_str_handler (Location invoc_locus,
   /* Get target filename from the macro invocation, which is treated as a path
      relative to the include!-ing file (currently being compiled).  */
   auto lit_expr
-    = parse_single_string_literal (AST::BuiltinMacro::IncludeStr,
+    = parse_single_string_literal (BuiltinMacro::IncludeStr,
 				   invoc.get_delim_tok_tree (), invoc_locus,
 				   invoc.get_expander ());
   if (lit_expr == nullptr)
@@ -527,7 +564,7 @@ MacroBuiltin::compile_error_handler (Location invoc_locus,
 				     AST::MacroInvocData &invoc)
 {
   auto lit_expr
-    = parse_single_string_literal (AST::BuiltinMacro::CompileError,
+    = parse_single_string_literal (BuiltinMacro::CompileError,
 				   invoc.get_delim_tok_tree (), invoc_locus,
 				   invoc.get_expander ());
   if (lit_expr == nullptr)
@@ -605,8 +642,7 @@ MacroBuiltin::concat_handler (Location invoc_locus, AST::MacroInvocData &invoc)
 
   auto pending_invocations = check_for_eager_invocations (expanded_expr);
   if (!pending_invocations.empty ())
-    return make_eager_builtin_invocation (AST::BuiltinMacro::Concat,
-					  invoc_locus,
+    return make_eager_builtin_invocation (BuiltinMacro::Concat, invoc_locus,
 					  invoc.get_delim_tok_tree (),
 					  std::move (pending_invocations));
 
@@ -672,7 +708,7 @@ MacroBuiltin::env_handler (Location invoc_locus, AST::MacroInvocData &invoc)
 
   auto pending = check_for_eager_invocations (expanded_expr);
   if (!pending.empty ())
-    return make_eager_builtin_invocation (AST::BuiltinMacro::Env, invoc_locus,
+    return make_eager_builtin_invocation (BuiltinMacro::Env, invoc_locus,
 					  invoc_token_tree,
 					  std::move (pending));
 
@@ -770,7 +806,7 @@ MacroBuiltin::include_handler (Location invoc_locus, AST::MacroInvocData &invoc)
   /* Get target filename from the macro invocation, which is treated as a path
      relative to the include!-ing file (currently being compiled).  */
   auto lit_expr
-    = parse_single_string_literal (AST::BuiltinMacro::Include,
+    = parse_single_string_literal (BuiltinMacro::Include,
 				   invoc.get_delim_tok_tree (), invoc_locus,
 				   invoc.get_expander ());
   if (lit_expr == nullptr)
@@ -877,6 +913,15 @@ MacroBuiltin::stringify_handler (Location invoc_locus,
   auto token
     = make_token (Token::make_string (invoc_locus, std::move (content)));
   return AST::Fragment ({node}, std::move (token));
-} // namespace Rust
+}
+
+AST::Fragment
+MacroBuiltin::sorry (Location invoc_locus, AST::MacroInvocData &invoc)
+{
+  rust_sorry_at (invoc_locus, "unimplemented builtin macro: %qs",
+		 invoc.get_path ().as_string ().c_str ());
+
+  return AST::Fragment::create_error ();
+}
 
 } // namespace Rust
diff --git a/gcc/rust/expand/rust-macro-builtins.h b/gcc/rust/expand/rust-macro-builtins.h
index bd4f1f95b74..10a38d7b93f 100644
--- a/gcc/rust/expand/rust-macro-builtins.h
+++ b/gcc/rust/expand/rust-macro-builtins.h
@@ -23,6 +23,51 @@
 #include "rust-ast-fragment.h"
 #include "rust-location.h"
 
+namespace Rust {
+
+// FIXME: Add a BuiltinMacro class which contains a name (or should it?), a
+// transcriber and extra info if necessary
+// then make a global map<string, BuiltinMacro>
+
+/**
+ * All builtin macros possible
+ */
+enum class BuiltinMacro
+{
+  Assert,
+  File,
+  Line,
+  Column,
+  IncludeBytes,
+  IncludeStr,
+  Stringify,
+  CompileError,
+  Concat,
+  Env,
+  OptionEnv,
+  Cfg,
+  Include,
+  FormatArgs,
+  FormatArgsNl,
+  ConcatIdents,
+  ModulePath,
+  Asm,
+  LlvmAsm,
+  GlobalAsm,
+  LogSyntax,
+  TraceMacros,
+  Test,
+  Bench,
+  TestCase,
+  GlobalAllocator,
+  CfgAccessible,
+  RustcDecodable,
+  RustcEncodable,
+};
+
+BuiltinMacro
+builtin_macro_from_string (const std::string &identifier);
+
 /**
  * This class provides a list of builtin macros implemented by the compiler.
  * The functions defined are called "builtin transcribers" in that they replace
@@ -59,11 +104,13 @@
  * This map is built as a static variable in the `insert_macro_def()` method
  * of the `Mappings` class.
  */
-
-namespace Rust {
 class MacroBuiltin
 {
 public:
+  static std::unordered_map<
+    std::string, std::function<AST::Fragment (Location, AST::MacroInvocData &)>>
+    builtin_transcribers;
+
   static AST::Fragment assert_handler (Location invoc_locus,
 				       AST::MacroInvocData &invoc);
 
@@ -99,7 +146,20 @@ public:
 
   static AST::Fragment line_handler (Location invoc_locus,
 				     AST::MacroInvocData &invoc);
+
+  static AST::Fragment sorry (Location invoc_locus, AST::MacroInvocData &invoc);
 };
 } // namespace Rust
 
+namespace std {
+template <> struct hash<Rust::BuiltinMacro>
+{
+  size_t operator() (const Rust::BuiltinMacro &macro) const noexcept
+  {
+    return hash<std::underlying_type<Rust::BuiltinMacro>::type> () (
+      static_cast<std::underlying_type<Rust::BuiltinMacro>::type> (macro));
+  }
+};
+} // namespace std
+
 #endif // RUST_MACRO_BUILTINS_H
diff --git a/gcc/rust/resolve/rust-early-name-resolver.cc b/gcc/rust/resolve/rust-early-name-resolver.cc
index 6e869d6a7c9..145b3931188 100644
--- a/gcc/rust/resolve/rust-early-name-resolver.cc
+++ b/gcc/rust/resolve/rust-early-name-resolver.cc
@@ -19,6 +19,7 @@
 #include "rust-early-name-resolver.h"
 #include "rust-ast-full.h"
 #include "rust-name-resolver.h"
+#include "rust-macro-builtins.h"
 
 namespace Rust {
 namespace Resolver {
@@ -873,7 +874,7 @@ EarlyNameResolver::visit (AST::MacroInvocation &invoc)
   if (is_builtin)
     {
       auto builtin_kind
-	= AST::builtin_macro_from_string (rules_def->get_rule_name ());
+	= builtin_macro_from_string (rules_def->get_rule_name ());
       invoc.map_to_builtin (builtin_kind);
     }
 
diff --git a/gcc/rust/util/rust-hir-map.cc b/gcc/rust/util/rust-hir-map.cc
index 8d001fd8241..5c711ca6ee3 100644
--- a/gcc/rust/util/rust-hir-map.cc
+++ b/gcc/rust/util/rust-hir-map.cc
@@ -868,23 +868,6 @@ Mappings::iterate_trait_items (
 void
 Mappings::insert_macro_def (AST::MacroRulesDefinition *macro)
 {
-  static std::map<
-    std::string, std::function<AST::Fragment (Location, AST::MacroInvocData &)>>
-    builtin_macros = {
-      {"assert", MacroBuiltin::assert_handler},
-      {"file", MacroBuiltin::file_handler},
-      {"line", MacroBuiltin::line_handler},
-      {"column", MacroBuiltin::column_handler},
-      {"include_bytes", MacroBuiltin::include_bytes_handler},
-      {"include_str", MacroBuiltin::include_str_handler},
-      {"stringify", MacroBuiltin::stringify_handler},
-      {"compile_error", MacroBuiltin::compile_error_handler},
-      {"concat", MacroBuiltin::concat_handler},
-      {"env", MacroBuiltin::env_handler},
-      {"cfg", MacroBuiltin::cfg_handler},
-      {"include", MacroBuiltin::include_handler},
-    };
-
   auto outer_attrs = macro->get_outer_attrs ();
   bool should_be_builtin
     = std::any_of (outer_attrs.begin (), outer_attrs.end (),
@@ -893,8 +876,9 @@ Mappings::insert_macro_def (AST::MacroRulesDefinition *macro)
 		   });
   if (should_be_builtin)
     {
-      auto builtin = builtin_macros.find (macro->get_rule_name ());
-      if (builtin != builtin_macros.end ())
+      auto builtin
+	= MacroBuiltin::builtin_transcribers.find (macro->get_rule_name ());
+      if (builtin != MacroBuiltin::builtin_transcribers.end ())
 	macro->set_builtin_transcriber (builtin->second);
       else
 	rust_error_at (macro->get_locus (),


More information about the Gcc-cvs mailing list