diff options
-rw-r--r-- | gcc/rust/expand/rust-expand-visitor.cc | 8 | ||||
-rw-r--r-- | gcc/rust/expand/rust-expand-visitor.h | 6 | ||||
-rw-r--r-- | gcc/rust/expand/rust-proc-macro.cc | 43 | ||||
-rw-r--r-- | gcc/rust/expand/rust-proc-macro.h | 79 | ||||
-rw-r--r-- | gcc/rust/rust-session-manager.cc | 3 | ||||
-rw-r--r-- | gcc/rust/util/rust-attributes.cc | 1 | ||||
-rw-r--r-- | gcc/rust/util/rust-hir-map.cc | 66 | ||||
-rw-r--r-- | 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 b95649d..04a899f 100644 --- a/gcc/rust/expand/rust-expand-visitor.cc +++ b/gcc/rust/expand/rust-expand-visitor.cc @@ -17,6 +17,7 @@ // <http://www.gnu.org/licenses/>. #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 <typename T> 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 <typename T> @@ -1585,8 +1587,8 @@ template <typename T> 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 <typename T> diff --git a/gcc/rust/expand/rust-expand-visitor.h b/gcc/rust/expand/rust-expand-visitor.h index 8589334..fd72d0b 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 22744cb..a53a5d8 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 779d3c7..244d274 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 <string> +#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<ProcMacro::Procmacro> 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 <typename T> + void expand_derive_proc_macro (T &item, std::string &trait_name) + {} + + template <typename T> + void expand_bang_proc_macro (T &item, AST::SimplePath &path) + {} + + template <typename T> + 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<TokenPtr> tokens; + AST::TokenCollector collector (tokens); + + collector.visit (item); + + std::vector<const_TokenPtr> vec; + for (auto i : collector.collect_tokens ()) + { + vec.push_back (std::const_pointer_cast<Token> (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 17f8465..bbcc569 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 0656b27..3403f48 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 3edbc20..706a29c 100644 --- a/gcc/rust/util/rust-hir-map.cc +++ b/gcc/rust/util/rust-hir-map.cc @@ -942,6 +942,72 @@ Mappings::get_exported_macros () } void +Mappings::insert_derive_proc_macro ( + std::pair<std::string, std::string> 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<std::string, std::string> 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<std::string, std::string> 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<std::string, std::string> 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<std::string, std::string> 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<std::string, std::string> 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) { visibility_map.insert ({id, visibility}); diff --git a/gcc/rust/util/rust-hir-map.h b/gcc/rust/util/rust-hir-map.h index 9f333f4..6e6a1c8 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<NodeId> &get_exported_macros (); + void insert_derive_proc_macro (std::pair<std::string, std::string> hierachy, + ProcMacro::CustomDerive macro); + void insert_bang_proc_macro (std::pair<std::string, std::string> hierachy, + ProcMacro::Bang macro); + void + insert_attribute_proc_macro (std::pair<std::string, std::string> hierachy, + ProcMacro::Attribute macro); + + bool lookup_derive_proc_macro (std::pair<std::string, std::string> hierachy, + ProcMacro::CustomDerive ¯o); + bool lookup_bang_proc_macro (std::pair<std::string, std::string> hierachy, + ProcMacro::Bang ¯o); + bool + lookup_attribute_proc_macro (std::pair<std::string, std::string> 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<CrateNum, std::set<HirId>> hirNodesWithinCrate; - // macros + // MBE macros std::map<NodeId, AST::MacroRulesDefinition *> macroMappings; std::map<NodeId, AST::MacroRulesDefinition *> macroInvocations; std::vector<NodeId> exportedMacros; + // Procedural macros + std::map<std::pair<std::string, std::string>, ProcMacro::CustomDerive> + procmacroDeriveMappings; + + std::map<std::pair<std::string, std::string>, ProcMacro::Bang> + procmacroBangMappings; + + std::map<std::pair<std::string, std::string>, ProcMacro::Attribute> + procmacroAttributeMappings; + // crate names std::map<CrateNum, std::string> crate_names; |