]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
gccrs: expand: Add prc macro expander and registration
authorPierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>
Thu, 18 May 2023 12:05:25 +0000 (14:05 +0200)
committerArthur Cohen <arthur.cohen@embecosm.com>
Tue, 16 Jan 2024 17:46:26 +0000 (18:46 +0100)
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 <pierre-emmanuel.patry@embecosm.com>
gcc/rust/expand/rust-expand-visitor.cc
gcc/rust/expand/rust-expand-visitor.h
gcc/rust/expand/rust-proc-macro.cc
gcc/rust/expand/rust-proc-macro.h
gcc/rust/rust-session-manager.cc
gcc/rust/util/rust-attributes.cc
gcc/rust/util/rust-hir-map.cc
gcc/rust/util/rust-hir-map.h

index b95649d5cd6fb5af7f993f4f0946741bd0e109b7..04a899f14970418a4e9feca0cfa28a037e9304e6 100644 (file)
@@ -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>
index 85893347defa10053efad807612e7f6ffb00360d..fd72d0b6771ad394ae897a019dbfec38d95a6b9d 100644 (file)
@@ -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
index 22744cb547d2c913b94e0ee84cbfb3cd18dba98c..a53a5d87ab972c142b3c54ec1f71ad138177a9d4 100644 (file)
@@ -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 &macro : 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
index 779d3c70fbc0223efd3ee27a21a6648e7dbdceb2..244d274773c3a022ae46db2fca89b40e77169490 100644 (file)
 #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 */
index c7bbe89b281cc4abb61739e70272a6d2e05e5b11..401d70590c467b6a610363a6ff139f294375a3d7 100644 (file)
@@ -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 ();
index 3a33d0629f2514970e39d041719059ac53c6ed79..4c7cb869861955d3b69607856def0193bb701197 100644 (file)
@@ -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},
index 93066f52d9536497556067429683f0e2a20a873c..2f6d02d41874fc33e0b4e7d1954711f3259b84e9 100644 (file)
@@ -941,6 +941,72 @@ Mappings::get_exported_macros ()
   return exportedMacros;
 }
 
+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 &macro)
+{
+  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 &macro)
+{
+  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 &macro)
+{
+  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)
 {
index 21d1bc0622a733de698adb698498da90cb0ebbb3..60498dec91ce64fa1be8ab259c6b51285faa0193 100644 (file)
@@ -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 &macro);
+  bool lookup_bang_proc_macro (std::pair<std::string, std::string> hierachy,
+                              ProcMacro::Bang &macro);
+  bool
+  lookup_attribute_proc_macro (std::pair<std::string, std::string> hierachy,
+                              ProcMacro::Attribute &macro);
+
   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;