public inbox for gcc-cvs@sourceware.org
help / color / mirror / Atom feed
* [gcc/devel/rust/master] Implement and test include_str eager expansion
@ 2023-02-28 22:36 Thomas Schwinge
  0 siblings, 0 replies; only message in thread
From: Thomas Schwinge @ 2023-02-28 22:36 UTC (permalink / raw)
  To: gcc-cvs

https://gcc.gnu.org/g:5c2ed969a2d58217797cf2e938c0f833a50d7cb4

commit 5c2ed969a2d58217797cf2e938c0f833a50d7cb4
Author: omkar-mohanty <franzohouser@gmail.com>
Date:   Thu Feb 16 10:10:24 2023 +0530

    Implement and test include_str eager expansion
    
    builtins: Implement eager expansion for include_str!()
    
    gcc/rust/ChangeLog:
    
            * expand/rust-macro-builtins.cc
            (MacroBuiltin::include_str_handler): eager expansion
            (make_macro_path_str): macto to string
            (parse_single_string_literal): check for eager invocation
            (MacroBuiltin::assert_handler): eager expansion
            (MacroBuiltin::include_bytes_handler): eager expansion
            (MacroBuiltin::include_str_handler): eager expansion
            (MacroBuiltin::compile_error_handler): eager expansion
            (MacroBuiltin::include_handler): eager expansion
    
    gcc/testsuite/ChangeLog:
    
            * rust/compile/builtin_macro_eager3.rs: New test.
    
    Signed-off-by: omkar-mohanty <franzohouser@gmail.com>

Diff:
---
 gcc/rust/expand/rust-macro-builtins.cc             | 160 ++++++++++++++-------
 gcc/testsuite/rust/compile/builtin_macro_eager3.rs |  16 +++
 2 files changed, 126 insertions(+), 50 deletions(-)

diff --git a/gcc/rust/expand/rust-macro-builtins.cc b/gcc/rust/expand/rust-macro-builtins.cc
index cf90b384cb5..d7f15784ceb 100644
--- a/gcc/rust/expand/rust-macro-builtins.cc
+++ b/gcc/rust/expand/rust-macro-builtins.cc
@@ -16,42 +16,24 @@
 // along with GCC; see the file COPYING3.  If not see
 // <http://www.gnu.org/licenses/>.
 
+#include "rust-system.h"
 #include "rust-macro-builtins.h"
+#include "rust-ast-fragment.h"
 #include "rust-ast.h"
+#include "rust-attribute-visitor.h"
 #include "rust-diagnostics.h"
+#include "rust-early-name-resolver.h"
 #include "rust-expr.h"
-#include "rust-session-manager.h"
-#include "rust-macro-invoc-lexer.h"
 #include "rust-lex.h"
+#include "rust-macro-invoc-lexer.h"
+#include "rust-macro.h"
 #include "rust-parse.h"
-#include "rust-early-name-resolver.h"
-#include "rust-attribute-visitor.h"
+#include "rust-session-manager.h"
 
 namespace Rust {
 namespace {
-
-/**
- * Shorthand function for creating unique_ptr tokens
- */
-static std::unique_ptr<AST::Token>
-make_token (const TokenPtr tok)
-{
-  return std::unique_ptr<AST::Token> (new AST::Token (tok));
-}
-
-std::unique_ptr<AST::Expr>
-make_string (Location locus, std::string value)
-{
-  return std::unique_ptr<AST::Expr> (
-    new AST::LiteralExpr (value, AST::Literal::STRING,
-			  PrimitiveCoreType::CORETYPE_STR, {}, locus));
-}
-
-// TODO: Is this correct?
-static AST::Fragment
-make_eager_builtin_invocation (
-  AST::BuiltinMacro kind, Location locus, AST::DelimTokenTree arguments,
-  std::vector<std::unique_ptr<AST::MacroInvocation>> &&pending_invocations)
+std::string
+make_macro_path_str (AST::BuiltinMacro kind)
 {
   std::string path_str;
 
@@ -93,6 +75,48 @@ make_eager_builtin_invocation (
       break;
     }
 
+  return path_str;
+}
+
+static std::vector<std::unique_ptr<AST::MacroInvocation>>
+check_for_eager_invocations (
+  std::vector<std::unique_ptr<AST::Expr>> &expressions)
+{
+  std::vector<std::unique_ptr<AST::MacroInvocation>> pending;
+
+  for (auto &expr : expressions)
+    if (expr->get_ast_kind () == AST::Kind::MACRO_INVOCATION)
+      pending.emplace_back (std::unique_ptr<AST::MacroInvocation> (
+	static_cast<AST::MacroInvocation *> (expr->clone_expr ().release ())));
+
+  return pending;
+}
+
+/**
+ * Shorthand function for creating unique_ptr tokens
+ */
+static std::unique_ptr<AST::Token>
+make_token (const TokenPtr tok)
+{
+  return std::unique_ptr<AST::Token> (new AST::Token (tok));
+}
+
+std::unique_ptr<AST::Expr>
+make_string (Location locus, std::string value)
+{
+  return std::unique_ptr<AST::Expr> (
+    new AST::LiteralExpr (value, AST::Literal::STRING,
+			  PrimitiveCoreType::CORETYPE_STR, {}, locus));
+}
+
+// TODO: Is this correct?
+static AST::Fragment
+make_eager_builtin_invocation (
+  AST::BuiltinMacro kind, Location locus, AST::DelimTokenTree arguments,
+  std::vector<std::unique_ptr<AST::MacroInvocation>> &&pending_invocations)
+{
+  auto path_str = make_macro_path_str (kind);
+
   std::unique_ptr<AST::Expr> node = AST::MacroInvocation::Builtin (
     kind,
     AST::MacroInvocData (AST::SimplePath (
@@ -195,8 +219,9 @@ try_expand_many_expr (Parser<MacroInvocLexer> &parser,
    and return the LiteralExpr for it. Allow for an optional trailing comma,
    but otherwise enforce that these are the only tokens.  */
 
-std::unique_ptr<AST::LiteralExpr>
-parse_single_string_literal (AST::DelimTokenTree &invoc_token_tree,
+std::unique_ptr<AST::Expr>
+parse_single_string_literal (AST::BuiltinMacro kind,
+			     AST::DelimTokenTree &invoc_token_tree,
 			     Location invoc_locus, MacroExpander *expander)
 {
   MacroInvocLexer lex (invoc_token_tree.to_token_stream ());
@@ -205,6 +230,7 @@ parse_single_string_literal (AST::DelimTokenTree &invoc_token_tree,
   auto last_token_id = macro_end_token (invoc_token_tree, parser);
 
   std::unique_ptr<AST::LiteralExpr> lit_expr = nullptr;
+  std::unique_ptr<AST::MacroInvocation> macro_invoc = nullptr;
 
   if (parser.peek_current_token ()->get_id () == STRING_LITERAL)
     {
@@ -219,11 +245,42 @@ parse_single_string_literal (AST::DelimTokenTree &invoc_token_tree,
   else if (parser.peek_current_token ()->get_id () == last_token_id)
     rust_error_at (invoc_locus, "macro takes 1 argument");
   else
-    rust_error_at (invoc_locus, "argument must be a string literal");
+    {
+      macro_invoc = parser.parse_macro_invocation (AST::AttrVec ());
+
+      parser.maybe_skip_token (COMMA);
+      if (parser.peek_current_token ()->get_id () != last_token_id)
+	{
+	  lit_expr = nullptr;
+	  rust_error_at (invoc_locus, "macro takes 1 argument");
+	}
+
+      if (macro_invoc != nullptr)
+	{
+	  auto path_str = make_macro_path_str (kind);
+
+	  auto pending_invocations
+	    = std::vector<std::unique_ptr<AST::MacroInvocation>> ();
+
+	  pending_invocations.push_back (std::move (macro_invoc));
+
+	  return AST::MacroInvocation::Builtin (
+	    kind,
+	    AST::MacroInvocData (AST::SimplePath ({AST::SimplePathSegment (
+				   path_str, invoc_locus)}),
+				 std::move (invoc_token_tree)),
+	    {}, invoc_locus, std::move (pending_invocations));
+	}
+      else
+	{
+	  rust_error_at (invoc_locus, "argument must be a string literal or a "
+				      "macro which expands to a string");
+	}
+    }
 
   parser.skip_token (last_token_id);
 
-  return lit_expr;
+  return std::unique_ptr<AST::Expr> (std::move (lit_expr));
 }
 
 /* Treat PATH as a path relative to the source file currently being
@@ -278,7 +335,7 @@ load_file_bytes (const char *filename)
 } // namespace
 
 AST::Fragment
-MacroBuiltin::assert_handler (Location, AST::MacroInvocData &)
+MacroBuiltin::assert_handler (Location invoc_locus, AST::MacroInvocData &invoc)
 {
   rust_debug ("assert!() called");
 
@@ -323,11 +380,14 @@ 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 (invoc.get_delim_tok_tree (), invoc_locus,
+    = parse_single_string_literal (AST::BuiltinMacro::IncludeBytes,
+				   invoc.get_delim_tok_tree (), invoc_locus,
 				   invoc.get_expander ());
   if (lit_expr == nullptr)
     return AST::Fragment::create_error ();
 
+  rust_assert (lit_expr->is_literal ());
+
   std::string target_filename
     = source_relative_path (lit_expr->as_string (), invoc_locus);
 
@@ -379,11 +439,19 @@ 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 (invoc.get_delim_tok_tree (), invoc_locus,
+    = parse_single_string_literal (AST::BuiltinMacro::IncludeStr,
+				   invoc.get_delim_tok_tree (), invoc_locus,
 				   invoc.get_expander ());
   if (lit_expr == nullptr)
     return AST::Fragment::create_error ();
 
+  if (!lit_expr->is_literal ())
+    {
+      auto token_tree = invoc.get_delim_tok_tree ();
+      return AST::Fragment ({AST::SingleASTNode (std::move (lit_expr))},
+			    token_tree.to_token_stream ());
+    }
+
   std::string target_filename
     = source_relative_path (lit_expr->as_string (), invoc_locus);
 
@@ -453,31 +521,20 @@ MacroBuiltin::compile_error_handler (Location invoc_locus,
 				     AST::MacroInvocData &invoc)
 {
   auto lit_expr
-    = parse_single_string_literal (invoc.get_delim_tok_tree (), invoc_locus,
+    = parse_single_string_literal (AST::BuiltinMacro::CompileError,
+				   invoc.get_delim_tok_tree (), invoc_locus,
 				   invoc.get_expander ());
   if (lit_expr == nullptr)
     return AST::Fragment::create_error ();
 
+  rust_assert (lit_expr->is_literal ());
+
   std::string error_string = lit_expr->as_string ();
   rust_error_at (invoc_locus, "%s", error_string.c_str ());
 
   return AST::Fragment::create_error ();
 }
 
-static std::vector<std::unique_ptr<AST::MacroInvocation>>
-check_for_eager_invocations (
-  std::vector<std::unique_ptr<AST::Expr>> &expressions)
-{
-  std::vector<std::unique_ptr<AST::MacroInvocation>> pending;
-
-  for (auto &expr : expressions)
-    if (expr->get_ast_kind () == AST::Kind::MACRO_INVOCATION)
-      pending.emplace_back (std::unique_ptr<AST::MacroInvocation> (
-	static_cast<AST::MacroInvocation *> (expr->clone_expr ().release ())));
-
-  return pending;
-}
-
 /* Expand builtin macro concat!(), which joins all the literal parameters
    into a string with no delimiter. */
 
@@ -707,11 +764,14 @@ 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 (invoc.get_delim_tok_tree (), invoc_locus,
+    = parse_single_string_literal (AST::BuiltinMacro::Include,
+				   invoc.get_delim_tok_tree (), invoc_locus,
 				   invoc.get_expander ());
   if (lit_expr == nullptr)
     return AST::Fragment::create_error ();
 
+  rust_assert (lit_expr->is_literal ());
+
   std::string filename
     = source_relative_path (lit_expr->as_string (), invoc_locus);
   auto target_filename
diff --git a/gcc/testsuite/rust/compile/builtin_macro_eager3.rs b/gcc/testsuite/rust/compile/builtin_macro_eager3.rs
new file mode 100644
index 00000000000..3b62cfe7c83
--- /dev/null
+++ b/gcc/testsuite/rust/compile/builtin_macro_eager3.rs
@@ -0,0 +1,16 @@
+#![feature(rustc_attrs)]
+
+#[rustc_builtin_macro]
+macro_rules! include_str {
+  () => {{}};
+}
+
+macro_rules! file1 {
+    () => {
+        "builtin_macro_include_str.rs"
+    };
+}
+
+fn main () {
+  include_str!(file1!()); // ok
+}

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2023-02-28 22:36 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-02-28 22:36 [gcc/devel/rust/master] Implement and test include_str eager expansion Thomas Schwinge

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).