From 663c4102a8ad43ec409e04d5ab834d38f161bdb5 Mon Sep 17 00:00:00 2001 From: Pierre-Emmanuel Patry Date: Thu, 18 May 2023 14:05:25 +0200 Subject: [PATCH] gccrs: expand: Add prc macro expander and registration Add containers and functions to the hir-map in order to register and lookup all three kind of procedural macros. Add a first draft for attribute procedural macro expansion. This expander still lack proper error handling as well as polishing. gcc/rust/ChangeLog: * util/rust-hir-map.cc (Mappings::insert_bang_proc_macro): Add a function to insert a new bang proc macro. (Mappings::lookup_bang_proc_macro): Add a function to lookup a bang procedural macro. (Mappings::insert_derive_proc_macro): Add a function to insert a derive procedural macro. (Mappings::lookup_derive_proc_macro): Add a function to lookup a derive procedural macro. (Mappings::insert_attribute_proc_macro): Add a function to insert an attribute procedural macro. (Mappings::lookup_attribute_proc_macro): Add a function to lookup an attribute procedural macro. * util/rust-hir-map.h: Add function prototypes. * expand/rust-expand-visitor.cc (ExpandVisitor::expand_outer_attribute): Implement expansion of outer attributes. (ExpandVisitor::expand_inner_attribute): Add call for inner attribute expansion. * expand/rust-expand-visitor.h: Add new procedural macro expander attribute. * expand/rust-proc-macro.cc (load_macros_array): Add a function to load the proc macro array from a given shared object. (load_macros): Add a function to retrieve procedural macro vector from a given shared object. (ProcMacroExpander::import_proc_macros): Add a function to load procedural macros from a given extern crate name. * expand/rust-proc-macro.h (RUST_PROC_MACRO_H): Add new proc-macro file. (class ProcMacroExpander): Add new ProcMacroExpander class. * rust-session-manager.cc (Session::expansion): Create new macro expander and feed it to the expand visitor. * util/rust-attributes.cc: Add macro_export builtin attribute. Signed-off-by: Pierre-Emmanuel Patry --- gcc/rust/expand/rust-expand-visitor.cc | 8 ++- gcc/rust/expand/rust-expand-visitor.h | 6 +- gcc/rust/expand/rust-proc-macro.cc | 43 ++++++++++++++ gcc/rust/expand/rust-proc-macro.h | 79 ++++++++++++++++++++++++++ gcc/rust/rust-session-manager.cc | 3 +- gcc/rust/util/rust-attributes.cc | 1 + gcc/rust/util/rust-hir-map.cc | 66 +++++++++++++++++++++ gcc/rust/util/rust-hir-map.h | 29 +++++++++- 8 files changed, 229 insertions(+), 6 deletions(-) diff --git a/gcc/rust/expand/rust-expand-visitor.cc b/gcc/rust/expand/rust-expand-visitor.cc index b95649d5cd6f..04a899f14970 100644 --- a/gcc/rust/expand/rust-expand-visitor.cc +++ b/gcc/rust/expand/rust-expand-visitor.cc @@ -17,6 +17,7 @@ // . #include "rust-expand-visitor.h" +#include "rust-proc-macro.h" #include "rust-attributes.h" #include "rust-ast.h" #include "rust-type.h" @@ -1551,7 +1552,8 @@ template void ExpandVisitor::expand_outer_attribute (T &item, AST::SimplePath &path) { - // FIXME: Implement outer attribute expansion + // FIXME: Retrieve path from segments + local use statements instead of string + proc_expander.expand_attribute_proc_macro (item, path); } template @@ -1585,8 +1587,8 @@ template void ExpandVisitor::expand_inner_attribute (T &item, AST::SimplePath &path) { - // TODO: Warn about instability ? - // FIXME: Implement expansion for that particular path + // FIXME: Retrieve path from segments + local use statements instead of string + proc_expander.expand_attribute_proc_macro (item, path); } template diff --git a/gcc/rust/expand/rust-expand-visitor.h b/gcc/rust/expand/rust-expand-visitor.h index 85893347defa..fd72d0b6771a 100644 --- a/gcc/rust/expand/rust-expand-visitor.h +++ b/gcc/rust/expand/rust-expand-visitor.h @@ -21,6 +21,7 @@ #include "rust-ast-visitor.h" #include "rust-macro-expand.h" +#include "rust-proc-macro.h" namespace Rust { @@ -39,7 +40,9 @@ is_builtin (AST::Attribute &attr); class ExpandVisitor : public AST::ASTVisitor { public: - ExpandVisitor (MacroExpander &expander) : expander (expander) {} + ExpandVisitor (MacroExpander &expander, ProcMacroExpander &proc_expander) + : expander (expander), proc_expander (proc_expander) + {} /* Expand all of the macro invocations currently contained in a crate */ void go (AST::Crate &crate); @@ -374,6 +377,7 @@ public: private: MacroExpander &expander; + ProcMacroExpander &proc_expander; }; } // namespace Rust diff --git a/gcc/rust/expand/rust-proc-macro.cc b/gcc/rust/expand/rust-proc-macro.cc index 22744cb547d2..a53a5d87ab97 100644 --- a/gcc/rust/expand/rust-proc-macro.cc +++ b/gcc/rust/expand/rust-proc-macro.cc @@ -61,4 +61,47 @@ load_macros (std::string path) array->macros + array->length); } +void +ProcMacroExpander::import_proc_macros (std::string extern_crate) +{ + auto path = session.extern_crates.find (extern_crate); + if (path == session.extern_crates.end ()) + { + // Extern crate path is not available. + // FIXME: Emit error + rust_error_at (Location (), "Cannot find requested proc macro crate"); + gcc_unreachable (); + } + auto macros = load_macros (path->second); + + std::string prefix = extern_crate + "::"; + for (auto ¯o : macros) + { + switch (macro.tag) + { + case ProcMacro::CUSTOM_DERIVE: + rust_debug ("Found one derive proc macro."); + mappings->insert_derive_proc_macro ( + std::make_pair (extern_crate, + macro.payload.custom_derive.trait_name), + macro.payload.custom_derive); + break; + case ProcMacro::ATTR: + rust_debug ("Found one attribute proc macro."); + mappings->insert_attribute_proc_macro ( + std::make_pair (extern_crate, macro.payload.attribute.name), + macro.payload.attribute); + break; + case ProcMacro::BANG: + rust_debug ("Found one bang proc macro."); + mappings->insert_bang_proc_macro ( + std::make_pair (extern_crate, macro.payload.bang.name), + macro.payload.bang); + break; + default: + gcc_unreachable (); + } + } +} + } // namespace Rust diff --git a/gcc/rust/expand/rust-proc-macro.h b/gcc/rust/expand/rust-proc-macro.h index 779d3c70fbc0..244d274773c3 100644 --- a/gcc/rust/expand/rust-proc-macro.h +++ b/gcc/rust/expand/rust-proc-macro.h @@ -17,6 +17,13 @@ #ifndef RUST_PROC_MACRO_H #define RUST_PROC_MACRO_H +#include +#include "rust-hir-map.h" +#include "rust-name-resolver.h" +#include "rust-session-manager.h" +#include "rust-ast.h" +#include "rust-ast-collector.h" +#include "rust-token-converter.h" #include "libproc_macro/proc_macro.h" namespace Rust { @@ -29,6 +36,78 @@ namespace Rust { const std::vector load_macros (std::string path); +class ProcMacroExpander +{ +public: + ProcMacroExpander (Session &session) + : session (session), has_changed_flag (false), + resolver (Resolver::Resolver::get ()), + mappings (Analysis::Mappings::get ()) + + {} + + ~ProcMacroExpander () = default; + + void import_proc_macros (std::string extern_crate); + + template + void expand_derive_proc_macro (T &item, std::string &trait_name) + {} + + template + void expand_bang_proc_macro (T &item, AST::SimplePath &path) + {} + + template + void expand_attribute_proc_macro (T &item, AST::SimplePath &path) + { + ProcMacro::Attribute macro; + + std::string crate = path.get_segments ()[0].get_segment_name (); + std::string name = path.get_segments ()[1].get_segment_name (); + if (!mappings->lookup_attribute_proc_macro (std::make_pair (crate, name), + macro)) + { + // FIXME: Resolve this path segment instead of taking it directly. + import_proc_macros (crate); + } + + if (!mappings->lookup_attribute_proc_macro (std::make_pair (crate, name), + macro)) + { + rust_error_at (Location (), "procedural macro %s not found", + name.c_str ()); + rust_assert (false); + } + // FIXME: Attach result back to the ast + std::vector tokens; + AST::TokenCollector collector (tokens); + + collector.visit (item); + + std::vector vec; + for (auto i : collector.collect_tokens ()) + { + vec.push_back (std::const_pointer_cast (i)); + } + + // FIXME: Handle attributes + macro.macro (ProcMacro::TokenStream::make_tokenstream (), convert (vec)); + } + + bool has_changed () const { return has_changed_flag; } + + void reset_changed_state () { has_changed_flag = false; } + +private: + Session &session; + bool has_changed_flag; + +public: + Resolver::Resolver *resolver; + Analysis::Mappings *mappings; +}; + } // namespace Rust #endif /* ! RUST_PROC_MACRO_H */ diff --git a/gcc/rust/rust-session-manager.cc b/gcc/rust/rust-session-manager.cc index c7bbe89b281c..401d70590c46 100644 --- a/gcc/rust/rust-session-manager.cc +++ b/gcc/rust/rust-session-manager.cc @@ -867,12 +867,13 @@ Session::expansion (AST::Crate &crate) /* expand by calling cxtctxt object's monotonic_expander's expand_crate * method. */ MacroExpander expander (crate, cfg, *this); + ProcMacroExpander proc_expander (*this); while (!fixed_point_reached && iterations < cfg.recursion_limit) { CfgStrip ().go (crate); Resolver::EarlyNameResolver ().go (crate); - ExpandVisitor (expander).go (crate); + ExpandVisitor (expander, proc_expander).go (crate); fixed_point_reached = !expander.has_changed (); expander.reset_changed_state (); diff --git a/gcc/rust/util/rust-attributes.cc b/gcc/rust/util/rust-attributes.cc index 3a33d0629f25..4c7cb8698619 100644 --- a/gcc/rust/util/rust-attributes.cc +++ b/gcc/rust/util/rust-attributes.cc @@ -43,6 +43,7 @@ static const BuiltinAttrDefinition __definitions[] {"rustc_builtin_macro", EXPANSION}, {"path", EXPANSION}, {"macro_use", NAME_RESOLUTION}, + {"macro_export", NAME_RESOLUTION}, // FIXME: This is not implemented yet, see // https://github.com/Rust-GCC/gccrs/issues/1475 {"target_feature", CODE_GENERATION}, diff --git a/gcc/rust/util/rust-hir-map.cc b/gcc/rust/util/rust-hir-map.cc index 93066f52d953..2f6d02d41874 100644 --- a/gcc/rust/util/rust-hir-map.cc +++ b/gcc/rust/util/rust-hir-map.cc @@ -941,6 +941,72 @@ Mappings::get_exported_macros () return exportedMacros; } +void +Mappings::insert_derive_proc_macro ( + std::pair hierarchy, ProcMacro::CustomDerive macro) +{ + auto it = procmacroDeriveMappings.find (hierarchy); + rust_assert (it == procmacroDeriveMappings.end ()); + + procmacroDeriveMappings[hierarchy] = macro; +} + +void +Mappings::insert_bang_proc_macro (std::pair hierarchy, + ProcMacro::Bang macro) +{ + auto it = procmacroBangMappings.find (hierarchy); + rust_assert (it == procmacroBangMappings.end ()); + + procmacroBangMappings[hierarchy] = macro; +} + +void +Mappings::insert_attribute_proc_macro ( + std::pair hierarchy, ProcMacro::Attribute macro) +{ + auto it = procmacroAttributeMappings.find (hierarchy); + rust_assert (it == procmacroAttributeMappings.end ()); + + procmacroAttributeMappings[hierarchy] = macro; +} + +bool +Mappings::lookup_derive_proc_macro ( + std::pair hierarchy, ProcMacro::CustomDerive ¯o) +{ + auto it = procmacroDeriveMappings.find (hierarchy); + if (it == procmacroDeriveMappings.end ()) + return false; + + macro = it->second; + return true; +} + +bool +Mappings::lookup_bang_proc_macro (std::pair hierarchy, + ProcMacro::Bang ¯o) +{ + auto it = procmacroBangMappings.find (hierarchy); + if (it == procmacroBangMappings.end ()) + return false; + + macro = it->second; + return true; +} + +bool +Mappings::lookup_attribute_proc_macro ( + std::pair hierarchy, ProcMacro::Attribute ¯o) +{ + auto it = procmacroAttributeMappings.find (hierarchy); + if (it == procmacroAttributeMappings.end ()) + return false; + + macro = it->second; + return true; +} + void Mappings::insert_visibility (NodeId id, Privacy::ModuleVisibility visibility) { diff --git a/gcc/rust/util/rust-hir-map.h b/gcc/rust/util/rust-hir-map.h index 21d1bc0622a7..60498dec91ce 100644 --- a/gcc/rust/util/rust-hir-map.h +++ b/gcc/rust/util/rust-hir-map.h @@ -28,6 +28,7 @@ #include "rust-hir-full-decls.h" #include "rust-lang-item.h" #include "rust-privacy-common.h" +#include "libproc_macro/proc_macro.h" namespace Rust { namespace Analysis { @@ -282,6 +283,22 @@ public: void insert_exported_macro (AST::MacroRulesDefinition &def); std::vector &get_exported_macros (); + void insert_derive_proc_macro (std::pair hierachy, + ProcMacro::CustomDerive macro); + void insert_bang_proc_macro (std::pair hierachy, + ProcMacro::Bang macro); + void + insert_attribute_proc_macro (std::pair hierachy, + ProcMacro::Attribute macro); + + bool lookup_derive_proc_macro (std::pair hierachy, + ProcMacro::CustomDerive ¯o); + bool lookup_bang_proc_macro (std::pair hierachy, + ProcMacro::Bang ¯o); + bool + lookup_attribute_proc_macro (std::pair hierachy, + ProcMacro::Attribute ¯o); + void insert_visibility (NodeId id, Privacy::ModuleVisibility visibility); bool lookup_visibility (NodeId id, Privacy::ModuleVisibility &def); @@ -350,11 +367,21 @@ private: // all hirid nodes std::map> hirNodesWithinCrate; - // macros + // MBE macros std::map macroMappings; std::map macroInvocations; std::vector exportedMacros; + // Procedural macros + std::map, ProcMacro::CustomDerive> + procmacroDeriveMappings; + + std::map, ProcMacro::Bang> + procmacroBangMappings; + + std::map, ProcMacro::Attribute> + procmacroAttributeMappings; + // crate names std::map crate_names; -- 2.43.5