From cf1287ee24c5c83b38737c50e3cd37ab62f3d279 Mon Sep 17 00:00:00 2001 From: Arthur Cohen Date: Wed, 3 May 2023 11:19:30 +0200 Subject: [PATCH] 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. --- 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 b558969eba4c..f36feda9970f 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 7216db8be53b..b6349a71ed3e 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 29a8b8b867b6..f0f1f8c9230f 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 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> + 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> @@ -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> &&pending_invocations) { auto path_str = make_macro_path_str (kind); @@ -224,7 +261,7 @@ try_expand_many_expr (Parser &parser, but otherwise enforce that these are the only tokens. */ std::unique_ptr -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 bd4f1f95b741..10a38d7b93f0 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 + +/** + * 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> + 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 +{ + size_t operator() (const Rust::BuiltinMacro ¯o) const noexcept + { + return hash::type> () ( + static_cast::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 6e869d6a7c92..145b39311882 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 8d001fd8241f..5c711ca6ee39 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> - 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 (), -- 2.47.2