public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
From: Arthur Cohen <arthur.cohen@embecosm.com>
To: gcc-patches@gcc.gnu.org
Cc: gcc-rust@gcc.gnu.org, Arthur Cohen <arthur.cohen@embecosm.com>
Subject: [PATCH 031/125] gccrs: format-args: Fix Rust interface and add input parsing.
Date: Thu,  1 Aug 2024 16:56:27 +0200	[thread overview]
Message-ID: <20240801145809.366388-33-arthur.cohen@embecosm.com> (raw)
In-Reply-To: <20240801145809.366388-2-arthur.cohen@embecosm.com>

gcc/rust/ChangeLog:

	* ast/rust-ast.cc: Make FormatArgs inherit from AST::Expr
	* ast/rust-builtin-ast-nodes.h: Improve FormatArg* nodes and helpers.
	* ast/rust-fmt.cc (Pieces::collect): Fix interface to match FFI function.
	* ast/rust-fmt.h (collect_pieces): Likewise.
	(struct Pieces): Add append_newline parameter.
	* expand/rust-macro-builtins.cc: Add proper parsing of format_args
	input.
	* hir/rust-ast-lower-base.cc: Include diagnostics header.

libgrust/ChangeLog:

	* libformat_parser/src/lib.rs: Switch interface to use more parser
	parameters.
	* libformat_parser/src/bin.rs: Use new interface.
---
 gcc/rust/ast/rust-ast.cc               |  51 +++++++
 gcc/rust/ast/rust-builtin-ast-nodes.h  | 133 ++++++++++++++++--
 gcc/rust/ast/rust-fmt.cc               |  38 +++++-
 gcc/rust/ast/rust-fmt.h                |  21 ++-
 gcc/rust/expand/rust-macro-builtins.cc | 182 +++++++++++++++++++------
 gcc/rust/hir/rust-ast-lower-base.cc    |   1 +
 libgrust/libformat_parser/src/bin.rs   |   5 +-
 libgrust/libformat_parser/src/lib.rs   |  63 ++++++---
 8 files changed, 416 insertions(+), 78 deletions(-)

diff --git a/gcc/rust/ast/rust-ast.cc b/gcc/rust/ast/rust-ast.cc
index 5d571b46622..f3dabc6cd0f 100644
--- a/gcc/rust/ast/rust-ast.cc
+++ b/gcc/rust/ast/rust-ast.cc
@@ -19,6 +19,7 @@ along with GCC; see the file COPYING3.  If not see
 
 #include "rust-ast.h"
 #include "optional.h"
+#include "rust-builtin-ast-nodes.h"
 #include "rust-system.h"
 #include "rust-ast-full.h"
 #include "rust-diagnostics.h"
@@ -5054,6 +5055,56 @@ FormatArgs::accept_vis (ASTVisitor &vis)
   vis.visit (*this);
 }
 
+std::string
+FormatArgs::as_string () const
+{
+  // FIXME(Arthur): Improve
+  return "FormatArgs";
+}
+
+location_t
+FormatArgs::get_locus () const
+{
+  rust_unreachable ();
+}
+
+bool
+FormatArgs::is_expr_without_block () const
+{
+  return false;
+}
+
+void
+FormatArgs::mark_for_strip ()
+{
+  marked_for_strip = true;
+}
+
+bool
+FormatArgs::is_marked_for_strip () const
+{
+  return marked_for_strip;
+}
+
+std::vector<Attribute> &
+FormatArgs::get_outer_attrs ()
+{
+  rust_unreachable ();
+}
+
+void FormatArgs::set_outer_attrs (std::vector<Attribute>)
+{
+  rust_unreachable ();
+}
+
+Expr *
+FormatArgs::clone_expr_impl () const
+{
+  std::cerr << "[ARTHUR] cloning FormatArgs! " << std::endl;
+
+  return new FormatArgs (*this);
+}
+
 } // namespace AST
 
 std::ostream &
diff --git a/gcc/rust/ast/rust-builtin-ast-nodes.h b/gcc/rust/ast/rust-builtin-ast-nodes.h
index 3998fbfb4a7..6e267173a55 100644
--- a/gcc/rust/ast/rust-builtin-ast-nodes.h
+++ b/gcc/rust/ast/rust-builtin-ast-nodes.h
@@ -59,9 +59,17 @@ namespace AST {
 //                      └─┘  └─┘
 //                      positions (could be names, numbers, empty, or `*`)
 
+// FIXME: Merge with the class below this one?
 class FormatArgumentKind
 {
 public:
+  enum class Kind
+  {
+    Normal,
+    Named,
+    Captured,
+  } kind;
+
   Identifier &get_ident ()
   {
     rust_assert (kind == Kind::Captured || kind == Kind::Named);
@@ -69,25 +77,90 @@ public:
     return ident.value ();
   }
 
-private:
-  enum class Kind
+  FormatArgumentKind (Kind kind, tl::optional<Identifier> ident)
+    : kind (kind), ident (ident)
+  {}
+
+  FormatArgumentKind (const FormatArgumentKind &other)
   {
-    Normal,
-    Named,
-    Captured,
-  } kind;
+    kind = other.kind;
+    ident = other.ident;
+  }
+
+  FormatArgumentKind operator= (const FormatArgumentKind &other)
+  {
+    kind = other.kind;
+    ident = other.ident;
 
+    return *this;
+  }
+
+private:
   tl::optional<Identifier> ident;
 };
 
 class FormatArgument
 {
+public:
+  static FormatArgument normal (std::unique_ptr<Expr> expr)
+  {
+    return FormatArgument (FormatArgumentKind::Kind::Normal, tl::nullopt,
+			   std::move (expr));
+  }
+
+  static FormatArgument named (Identifier ident, std::unique_ptr<Expr> expr)
+  {
+    return FormatArgument (FormatArgumentKind::Kind::Named, ident,
+			   std::move (expr));
+  }
+
+  static FormatArgument captured (Identifier ident, std::unique_ptr<Expr> expr)
+  {
+    return FormatArgument (FormatArgumentKind::Kind::Captured, ident,
+			   std::move (expr));
+  }
+
+  FormatArgument (const FormatArgument &other)
+    : kind (other.kind), expr (other.expr->clone_expr ())
+  {}
+
+  FormatArgument operator= (const FormatArgument &other)
+  {
+    kind = other.kind;
+    expr = other.expr->clone_expr ();
+
+    return *this;
+  }
+
+private:
+  FormatArgument (FormatArgumentKind::Kind kind, tl::optional<Identifier> ident,
+		  std::unique_ptr<Expr> expr)
+    : kind (FormatArgumentKind (kind, ident)), expr (std::move (expr))
+  {}
+
   FormatArgumentKind kind;
   std::unique_ptr<Expr> expr;
 };
 
 class FormatArguments
 {
+public:
+  FormatArguments () {}
+  FormatArguments (FormatArguments &&) = default;
+  FormatArguments (const FormatArguments &other)
+  {
+    args = std::vector<FormatArgument> ();
+    args.reserve (other.args.size ());
+
+    for (const auto &arg : other.args)
+      args.emplace_back (arg);
+  };
+
+  FormatArguments &operator= (const FormatArguments &other) = default;
+
+  void push (FormatArgument &&elt) { args.emplace_back (std::move (elt)); }
+
+private:
   std::vector<FormatArgument> args;
 };
 
@@ -100,7 +173,7 @@ class FormatArguments
 // format_args!("result: {}", some_result))` -> `format_args!("heyo result: {}",
 // some_result)`
 // FIXME: Move to rust-macro.h
-class FormatArgs : public Visitable
+class FormatArgs : public Expr
 {
 public:
   enum class Newline
@@ -109,18 +182,56 @@ public:
     No
   };
 
-  FormatArgs (location_t loc, Fmt::PieceSlice template_str,
-	      FormatArguments arguments)
+  FormatArgs (location_t loc, Fmt::Pieces &&template_str,
+	      FormatArguments &&arguments)
     : loc (loc), template_str (std::move (template_str)),
       arguments (std::move (arguments))
   {}
 
-  void accept_vis (AST::ASTVisitor &vis);
+  FormatArgs (FormatArgs &&other)
+    : loc (std::move (other.loc)),
+      template_str (std::move (other.template_str)),
+      arguments (std::move (other.arguments))
+  {
+    std::cerr << "[ARTHUR] moving FormatArgs" << std::endl;
+  }
+
+  // FIXME: This might be invalid - we are reusing the same memory allocated
+  // on the Rust side for `other`. This is probably valid as long as we only
+  // ever read that memory and never write to it.
+  FormatArgs (const FormatArgs &other)
+    : loc (other.loc), template_str (other.template_str),
+      arguments (other.arguments)
+  {
+    std::cerr << "[ARTHUR] copying FormatArgs" << std::endl;
+  }
+
+  // FormatArgs &operator= (const FormatArgs &other) = default;
+  //   : template_str (other.template_str), arguments (other.arguments)
+  // {}
+
+  void accept_vis (AST::ASTVisitor &vis) override;
 
 private:
   location_t loc;
-  Fmt::PieceSlice template_str;
+  // FIXME: This probably needs to be a separate type - it is one in rustc's
+  // expansion of format_args!(). There is extra handling associated with it.
+  // we can maybe do that in rust-fmt.cc? in collect_pieces()? like do the
+  // transformation into something we can handle better
+  Fmt::Pieces template_str;
   FormatArguments arguments;
+
+  bool marked_for_strip = false;
+
+protected:
+  virtual std::string as_string () const override;
+  virtual location_t get_locus () const override;
+  virtual bool is_expr_without_block () const override;
+  virtual void mark_for_strip () override;
+  virtual bool is_marked_for_strip () const override;
+  virtual std::vector<Attribute> &get_outer_attrs () override;
+  virtual void set_outer_attrs (std::vector<Attribute>) override;
+  virtual Expr *clone_expr_impl () const override;
 };
 
 } // namespace AST
diff --git a/gcc/rust/ast/rust-fmt.cc b/gcc/rust/ast/rust-fmt.cc
index 511e94740c5..c367e30d546 100644
--- a/gcc/rust/ast/rust-fmt.cc
+++ b/gcc/rust/ast/rust-fmt.cc
@@ -23,9 +23,9 @@ namespace Rust {
 namespace Fmt {
 
 Pieces
-Pieces::collect (std::string &&to_parse)
+Pieces::collect (std::string &&to_parse, bool append_newline)
 {
-  auto piece_slice = collect_pieces (to_parse.c_str ());
+  auto piece_slice = collect_pieces (to_parse.c_str (), append_newline);
 
   rust_debug ("[ARTHUR] %p, %lu", (const void *) piece_slice.base_ptr,
 	      piece_slice.len);
@@ -37,7 +37,39 @@ Pieces::collect (std::string &&to_parse)
   return Pieces (piece_slice, std::move (to_parse));
 }
 
-Pieces::~Pieces () { destroy_pieces (slice); }
+Pieces::~Pieces ()
+{
+  std::cerr << "Arthur: destoying pieces. this: " << (void *) this
+	    << " slice: " << slice.base_ptr << std::endl;
+  destroy_pieces (slice);
+}
+
+Pieces::Pieces (const Pieces &other) : to_parse (other.to_parse)
+{
+  slice = clone_pieces (other.slice.base_ptr, other.slice.len, other.slice.cap);
+  std::cerr << "Arthur: copying pieces: other.to_parse: "
+	    << (void *) other.to_parse.c_str ()
+	    << " ours to_parse: " << (void *) to_parse.c_str () << std::endl;
+  // auto pieces = std::vector (slice.base_ptr, slice.base_ptr + slice.len);
+}
+
+Pieces &
+Pieces::operator= (const Pieces &other)
+{
+  slice = clone_pieces (other.slice.base_ptr, other.slice.len, other.slice.cap);
+  to_parse = other.to_parse;
+
+  return *this;
+}
+
+Pieces::Pieces (Pieces &&other)
+  : slice (
+    clone_pieces (other.slice.base_ptr, other.slice.len, other.slice.cap)),
+    to_parse (std::move (other.to_parse))
+{
+  std::cerr << "Arthur: moving pieces. to_parse: " << (void *) to_parse.c_str ()
+	    << " base_ptr/slice: " << (void *) slice.base_ptr << std::endl;
+}
 
 } // namespace Fmt
 } // namespace Rust
diff --git a/gcc/rust/ast/rust-fmt.h b/gcc/rust/ast/rust-fmt.h
index 0bf9695bb6d..22447c4eba0 100644
--- a/gcc/rust/ast/rust-fmt.h
+++ b/gcc/rust/ast/rust-fmt.h
@@ -222,7 +222,7 @@ struct Piece
 
   struct NextArgument_Body
   {
-    const Argument *_0;
+    Argument _0;
   };
 
   Tag tag;
@@ -243,7 +243,10 @@ struct PieceSlice
 extern "C" {
 
 PieceSlice
-collect_pieces (const char *input);
+collect_pieces (const char *input, bool append_newline);
+
+PieceSlice
+clone_pieces (const Piece *base_ptr, size_t len, size_t cap);
 
 void destroy_pieces (PieceSlice);
 
@@ -251,9 +254,21 @@ void destroy_pieces (PieceSlice);
 
 struct Pieces
 {
-  static Pieces collect (std::string &&to_parse);
+  static Pieces collect (std::string &&to_parse, bool append_newline);
   ~Pieces ();
 
+  Pieces (const Pieces &other);
+  Pieces &operator= (const Pieces &other);
+
+  Pieces (Pieces &&other);
+
+  // {
+  //   slice = clone_pieces (&other.slice);
+  //   to_parse = other.to_parse;
+
+  //   return *this;
+  // }
+
 private:
   Pieces (PieceSlice slice, std::string &&to_parse)
     : slice (slice), to_parse (std::move (to_parse))
diff --git a/gcc/rust/expand/rust-macro-builtins.cc b/gcc/rust/expand/rust-macro-builtins.cc
index 9e6716c5975..b42d1ec9367 100644
--- a/gcc/rust/expand/rust-macro-builtins.cc
+++ b/gcc/rust/expand/rust-macro-builtins.cc
@@ -16,6 +16,7 @@
 // along with GCC; see the file COPYING3.  If not see
 // <http://www.gnu.org/licenses/>.
 
+#include "expected.h"
 #include "libproc_macro_internal/tokenstream.h"
 #include "rust-ast-full-decls.h"
 #include "rust-builtin-ast-nodes.h"
@@ -35,6 +36,7 @@
 #include "rust-session-manager.h"
 #include "rust-attribute-values.h"
 #include "rust-fmt.h"
+#include "rust-token.h"
 
 namespace Rust {
 
@@ -956,34 +958,116 @@ MacroBuiltin::stringify_handler (location_t invoc_locus,
   return AST::Fragment ({node}, std::move (token));
 }
 
-tl::optional<AST::Fragment>
-MacroBuiltin::format_args_handler (location_t invoc_locus,
-				   AST::MacroInvocData &invoc,
-				   AST::FormatArgs::Newline nl)
+struct FormatArgsInput
 {
-  // Remove the delimiters from the macro invocation:
-  // the invoc data for `format_args!(fmt, arg1, arg2)` is `(fmt, arg1, arg2)`,
-  // so we pop the front and back to remove the parentheses (or curly brackets,
-  // or brackets)
-  auto tokens = invoc.get_delim_tok_tree ().to_token_stream ();
-  tokens.erase (tokens.begin ());
-  tokens.pop_back ();
+  std::unique_ptr<AST::Expr> format_str;
+  AST::FormatArguments args;
+  // bool is_literal?
+};
 
-  auto append_newline = nl == AST::FormatArgs::Newline::Yes ? true : false;
-  auto fmt_arg
-    = parse_single_string_literal (append_newline ? BuiltinMacro::FormatArgsNl
-						  : BuiltinMacro::FormatArgs,
-				   invoc.get_delim_tok_tree (), invoc_locus,
-				   invoc.get_expander ());
+struct FormatArgsParseError
+{
+  enum class Kind
+  {
+    MissingArguments
+  } kind;
+};
+
+static tl::expected<FormatArgsInput, FormatArgsParseError>
+format_args_parse_arguments (AST::MacroInvocData &invoc)
+{
+  MacroInvocLexer lex (invoc.get_delim_tok_tree ().to_token_stream ());
+  Parser<MacroInvocLexer> parser (lex);
+
+  // TODO: check if EOF - return that format_args!() requires at least one
+  // argument
 
-  if (!fmt_arg->is_literal ())
+  auto args = AST::FormatArguments ();
+  auto last_token_id = macro_end_token (invoc.get_delim_tok_tree (), parser);
+  std::unique_ptr<AST::Expr> format_str = nullptr;
+
+  // TODO: Handle the case where we're not parsing a string literal (macro
+  // invocation for e.g.)
+  if (parser.peek_current_token ()->get_id () == STRING_LITERAL)
+    format_str = parser.parse_literal_expr ();
+
+  // TODO: Allow implicit captures ONLY if the the first arg is a string literal
+  // and not a macro invocation
+
+  // TODO: How to consume all of the arguments until the delimiter?
+
+  // TODO: What we then want to do is as follows:
+  // for each token, check if it is an identifier
+  //     yes? is the next token an equal sign (=)
+  //          yes?
+  //              -> if that identifier is already present in our map, error
+  //              out
+  //              -> parse an expression, return a FormatArgument::Named
+  //     no?
+  //         -> if there have been named arguments before, error out
+  //         (positional after named error)
+  //         -> parse an expression, return a FormatArgument::Normal
+  while (parser.peek_current_token ()->get_id () != last_token_id)
     {
-      rust_sorry_at (
-	invoc_locus,
-	"cannot yet use eager macro invocations as format strings");
-      return AST::Fragment::create_empty ();
+      parser.skip_token (COMMA);
+
+      if (parser.peek_current_token ()->get_id () == IDENTIFIER
+	  && parser.peek (1)->get_id () == EQUAL)
+	{
+	  // FIXME: This is ugly - just add a parser.parse_identifier()?
+	  auto ident_tok = parser.peek_current_token ();
+	  auto ident = Identifier (ident_tok);
+
+	  parser.skip_token (IDENTIFIER);
+	  parser.skip_token (EQUAL);
+
+	  auto expr = parser.parse_expr ();
+
+	  // TODO: Handle graciously
+	  if (!expr)
+	    rust_unreachable ();
+
+	  args.push (AST::FormatArgument::named (ident, std::move (expr)));
+	}
+      else
+	{
+	  auto expr = parser.parse_expr ();
+
+	  // TODO: Handle graciously
+	  if (!expr)
+	    rust_unreachable ();
+
+	  args.push (AST::FormatArgument::normal (std::move (expr)));
+	}
+      // we need to skip commas, don't we?
     }
 
+  return FormatArgsInput{std::move (format_str), std::move (args)};
+}
+
+tl::optional<AST::Fragment>
+MacroBuiltin::format_args_handler (location_t invoc_locus,
+				   AST::MacroInvocData &invoc,
+				   AST::FormatArgs::Newline nl)
+{
+  auto input = format_args_parse_arguments (invoc);
+
+  // auto fmt_arg
+  //   // FIXME: this eneds to be split up into a smaller function
+  //   = parse_single_string_literal (append_newline ?
+  //   BuiltinMacro::FormatArgsNl
+  // 				  : BuiltinMacro::FormatArgs,
+  // 		   invoc.get_delim_tok_tree (), invoc_locus,
+  // 		   invoc.get_expander ());
+
+  //  if (!fmt_arg->is_literal ())
+  //    {
+  //      rust_sorry_at (
+  // invoc_locus,
+  // "cannot yet use eager macro invocations as format strings");
+  //      return AST::Fragment::create_empty ();
+  //    }
+
   // FIXME: We need to handle this
   // // if it is not a literal, it's an eager macro invocation - return it
   // if (!fmt_expr->is_literal ())
@@ -993,38 +1077,54 @@ MacroBuiltin::format_args_handler (location_t invoc_locus,
   // 	    token_tree.to_token_stream ());
   //   }
 
-  auto fmt_str = static_cast<AST::LiteralExpr &> (*fmt_arg.get ());
+  // auto fmt_str = static_cast<AST::LiteralExpr &> (*fmt_arg.get ());
 
   // Switch on the format string to know if the string is raw or cooked
-  switch (fmt_str.get_lit_type ())
-    {
-    // case AST::Literal::RAW_STRING:
-    case AST::Literal::STRING:
-      break;
-    case AST::Literal::CHAR:
-    case AST::Literal::BYTE:
-    case AST::Literal::BYTE_STRING:
-    case AST::Literal::INT:
-    case AST::Literal::FLOAT:
-    case AST::Literal::BOOL:
-    case AST::Literal::ERROR:
-      rust_unreachable ();
-    }
+  // switch (fmt_str.get_lit_type ())
+  //   {
+  //   // case AST::Literal::RAW_STRING:
+  //   case AST::Literal::STRING:
+  //     break;
+  //   case AST::Literal::CHAR:
+  //   case AST::Literal::BYTE:
+  //   case AST::Literal::BYTE_STRING:
+  //   case AST::Literal::INT:
+  //   case AST::Literal::FLOAT:
+  //   case AST::Literal::BOOL:
+  //   case AST::Literal::ERROR:
+  //     rust_unreachable ();
+  //   }
+
+  // Remove the delimiters from the macro invocation:
+  // the invoc data for `format_args!(fmt, arg1, arg2)` is `(fmt, arg1, arg2)`,
+  // so we pop the front and back to remove the parentheses (or curly brackets,
+  // or brackets)
+  auto tokens = invoc.get_delim_tok_tree ().to_token_stream ();
+  tokens.erase (tokens.begin ());
+  tokens.pop_back ();
 
   std::stringstream stream;
   for (const auto &tok : tokens)
     stream << tok->as_string () << ' ';
 
-  rust_debug ("[ARTHUR]: `%s`", stream.str ().c_str ());
-
-  auto pieces = Fmt::Pieces::collect (stream.str ());
+  auto append_newline = nl == AST::FormatArgs::Newline::Yes ? true : false;
+  auto pieces = Fmt::Pieces::collect (stream.str (), append_newline);
 
   // TODO:
   // do the transformation into an AST::FormatArgs node
   // return that
   // expand it during lowering
 
-  return AST::Fragment::create_empty ();
+  // TODO: we now need to take care of creating `unfinished_literal`? this is
+  // for creating the `template`
+
+  auto fmt_args_node = new AST::FormatArgs (invoc_locus, std::move (pieces),
+					    std::move (input->args));
+  auto node = std::unique_ptr<AST::Expr> (fmt_args_node);
+  auto single_node = AST::SingleASTNode (std::move (node));
+
+  return AST::Fragment ({std::move (single_node)},
+			invoc.get_delim_tok_tree ().to_token_stream ());
 }
 
 tl::optional<AST::Fragment>
diff --git a/gcc/rust/hir/rust-ast-lower-base.cc b/gcc/rust/hir/rust-ast-lower-base.cc
index fa37d62d026..54c05208e7b 100644
--- a/gcc/rust/hir/rust-ast-lower-base.cc
+++ b/gcc/rust/hir/rust-ast-lower-base.cc
@@ -22,6 +22,7 @@
 #include "rust-ast-lower-extern.h"
 #include "rust-ast.h"
 #include "rust-attribute-values.h"
+#include "rust-diagnostics.h"
 #include "rust-item.h"
 #include "rust-system.h"
 
diff --git a/libgrust/libformat_parser/src/bin.rs b/libgrust/libformat_parser/src/bin.rs
index 4b1f903ad5f..5f46497c946 100644
--- a/libgrust/libformat_parser/src/bin.rs
+++ b/libgrust/libformat_parser/src/bin.rs
@@ -2,6 +2,9 @@ use libformat_parser::rust;
 
 fn main() {
     dbg!(rust::collect_pieces(
-        std::env::args().nth(1).unwrap().as_str()
+        std::env::args().nth(1).unwrap().as_str(),
+        None,
+        None,
+        false
     ));
 }
diff --git a/libgrust/libformat_parser/src/lib.rs b/libgrust/libformat_parser/src/lib.rs
index c164578a103..6bf78c4f2a8 100644
--- a/libgrust/libformat_parser/src/lib.rs
+++ b/libgrust/libformat_parser/src/lib.rs
@@ -77,20 +77,15 @@ mod ffi {
 
     /// A piece is a portion of the format string which represents the next part
     /// to emit. These are emitted as a stream by the `Parser` class.
-    #[derive(Clone, Debug, PartialEq)]
+    #[derive(Debug, Clone, PartialEq)]
     #[repr(C)]
     pub enum Piece<'a> {
         /// A literal string which should directly be emitted
         String(&'a str),
         /// This describes that formatting should process the next argument (as
         /// specified inside) for emission.
-        NextArgument(*const Argument<'a>),
-    }
-
-    impl<'a> Drop for Piece<'a> {
-        fn drop(&mut self) {
-            println!("dropping Piece: {:?}", self)
-        }
+        // do we need a pointer here? we're doing big cloning anyway
+        NextArgument(Argument<'a>),
     }
 
     /// Representation of an argument specification.
@@ -216,7 +211,7 @@ mod ffi {
                     let ptr = Box::leak(x);
                     let dst = Into::<Argument>::into(*ptr);
 
-                    Piece::NextArgument(&dst as *const Argument)
+                    Piece::NextArgument(dst)
                 }
             }
         }
@@ -321,8 +316,13 @@ mod ffi {
 pub mod rust {
     use generic_format_parser::{ParseMode, Parser, Piece};
 
-    pub fn collect_pieces(input: &str) -> Vec<Piece<'_>> {
-        let parser = Parser::new(input, None, None, true, ParseMode::Format);
+    pub fn collect_pieces(
+        input: &str,
+        style: Option<usize>,
+        snippet: Option<String>,
+        append_newline: bool,
+    ) -> Vec<Piece<'_>> {
+        let parser = Parser::new(input, style, snippet, append_newline, ParseMode::Format);
 
         parser.into_iter().collect()
     }
@@ -337,16 +337,18 @@ pub struct PieceSlice {
 }
 
 #[no_mangle]
-pub extern "C" fn collect_pieces(input: *const libc::c_char) -> PieceSlice {
+pub extern "C" fn collect_pieces(input: *const libc::c_char, append_newline: bool) -> PieceSlice {
+    dbg!(input);
+
     // FIXME: Add comment
     let str = unsafe { CStr::from_ptr(input) };
-    dbg!(str);
 
     // FIXME: No unwrap
-    let pieces: Vec<ffi::Piece<'_>> = rust::collect_pieces(str.to_str().unwrap())
-        .into_iter()
-        .map(Into::into)
-        .collect();
+    let pieces: Vec<ffi::Piece<'_>> =
+        rust::collect_pieces(str.to_str().unwrap(), None, None, append_newline)
+            .into_iter()
+            .map(Into::into)
+            .collect();
 
     println!("[ARTHUR]: debug: {:?}, {:?}", pieces.as_ptr(), pieces.len());
 
@@ -358,6 +360,29 @@ pub extern "C" fn collect_pieces(input: *const libc::c_char) -> PieceSlice {
 }
 
 #[no_mangle]
-pub extern "C" fn destroy_pieces(PieceSlice { base_ptr, len, cap }: PieceSlice) {
-    let _ = unsafe { Vec::from_raw_parts(base_ptr, len, cap) };
+pub unsafe extern "C" fn destroy_pieces(PieceSlice { base_ptr, len, cap }: PieceSlice) {
+    eprintln!("[ARTHUR] destroying pieces: {base_ptr:?} {len} {cap}");
+    drop(Vec::from_raw_parts(base_ptr, len, cap));
+}
+
+#[no_mangle]
+pub extern "C" fn clone_pieces(
+    base_ptr: *mut ffi::Piece<'static>,
+    len: usize,
+    cap: usize,
+) -> PieceSlice {
+    eprintln!("[ARTHUR] cloning pieces: {base_ptr:?} {len} {cap}");
+
+    let v = unsafe { Vec::from_raw_parts(base_ptr, len, cap) };
+
+    let cloned_v = v.clone();
+
+    // FIXME: Add documentation
+    v.leak();
+
+    PieceSlice {
+        len: cloned_v.len(),
+        cap: cloned_v.capacity(),
+        base_ptr: dbg!(cloned_v.leak().as_mut_ptr()),
+    }
 }
-- 
2.45.2


  parent reply	other threads:[~2024-08-01 14:58 UTC|newest]

Thread overview: 130+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-08-01 14:55 [PATCH 001/125] Rust: Make 'tree'-level 'MAIN_NAME_P' work Arthur Cohen
2024-08-01 14:55 ` [PATCH 002/125] gccrs: Fix false positive for top-level AltPattern Arthur Cohen
2024-08-01 14:55 ` [PATCH 003/125] gccrs: minor cleanup in langhook.type_for_mode Arthur Cohen
2024-08-01 14:56 ` [PATCH 004/125] gccrs: fmt: Start working on format_args!() parser Arthur Cohen
2024-08-01 14:56 ` [PATCH 005/125] gccrs: libgrust: Add format_parser library Arthur Cohen
2024-08-05  8:18   ` Don't override 'LIBS' if '--enable-languages=rust'; use 'CRAB1_LIBS' (was: [PATCH 005/125] gccrs: libgrust: Add format_parser library) Thomas Schwinge
2024-11-23 20:09   ` Rust: Work around 'error[E0658]: `let...else` statements are unstable' " Thomas Schwinge
2024-11-25 10:24     ` Rust: Work around 'error[E0658]: `let...else` statements are unstable' Arthur Cohen
2024-08-01 14:56 ` [PATCH 006/125] gccrs: Add 'gcc/rust/Make-lang.in:LIBFORMAT_PARSER' Arthur Cohen
2024-08-05  8:45   ` Inline 'gcc/rust/Make-lang.in:RUST_LIBDEPS' (was: [PATCH 006/125] gccrs: Add 'gcc/rust/Make-lang.in:LIBFORMAT_PARSER') Thomas Schwinge
2024-08-01 14:56 ` [PATCH 007/125] gccrs: libgrust: Vendor Rust dependencies Arthur Cohen
2024-08-01 14:56 ` [PATCH 008/125] Rust: Don't cache 'libformat_parser.a' Arthur Cohen
2024-08-01 14:56 ` [PATCH 009/125] Rust: Move 'libformat_parser' build into the GCC build directory Arthur Cohen
2024-08-01 14:56 ` [PATCH 010/125] Rust: Move 'libformat_parser' build into libgrust Arthur Cohen
2024-08-01 14:56 ` [PATCH 011/125] gccrs: libformat_parser: Add FFI safe interface Arthur Cohen
2024-08-01 14:56 ` [PATCH 012/125] gccrs: libformat_parser: Start experimenting with cbindgen Arthur Cohen
2024-08-01 14:56 ` [PATCH 013/125] gccrs: libformat_parser: Update header and remove old interface Arthur Cohen
2024-08-01 14:56 ` [PATCH 014/125] gccrs: libformat_parser: Send boxed values across FFI properly Arthur Cohen
2024-08-01 14:56 ` [PATCH 015/125] gccrs: format_args: Parse format string properly Arthur Cohen
2024-08-01 14:56 ` [PATCH 016/125] gccrs: format_args: Parse entire token invocation Arthur Cohen
2024-08-01 14:56 ` [PATCH 017/125] gccrs: rust-fmt: Store parsed string in Pieces struct Arthur Cohen
2024-08-01 14:56 ` [PATCH 018/125] gccrs: libformat_parser: Fix Rust warnings Arthur Cohen
2024-08-01 14:56 ` [PATCH 019/125] gccrs: format-parser: Add `is_some_and` method for Option<T> Arthur Cohen
2024-08-01 14:56 ` [PATCH 020/125] gccrs: Adjust error checks to match name resolution 2.0 Arthur Cohen
2024-08-01 14:56 ` [PATCH 021/125] gccrs: Fix small FixMe task in rust macro builtins Arthur Cohen
2024-08-01 14:56 ` [PATCH 022/125] gccrs: lang-items: Cleanup parsing and lookups of lang items Arthur Cohen
2024-08-01 14:56 ` [PATCH 023/125] gccrs: lang-items: Make lang items enum stronger, rename class, cleanup ns Arthur Cohen
2024-08-01 14:56 ` [PATCH 024/125] gccrs: extern-types: Declare external types in name resolver Arthur Cohen
2024-08-01 14:56 ` [PATCH 025/125] gccrs: hir: Add ExternalTypeItem node Arthur Cohen
2024-08-01 14:56 ` [PATCH 026/125] gccrs: extern-types: Lower to HIR::ExternalTypeItem properly Arthur Cohen
2024-08-01 14:56 ` [PATCH 027/125] gccrs: Make DefaultResolver visit more of the AST Arthur Cohen
2024-08-01 14:56 ` [PATCH 028/125] gccrs: ast: Add base nodes for FormatArgs Arthur Cohen
2024-08-01 14:56 ` [PATCH 029/125] gccrs: macro-builtins: Add newline generic format_args!() handler Arthur Cohen
2024-08-01 14:56 ` [PATCH 030/125] gccrs: parser: Add peek(n) method to parser Arthur Cohen
2024-08-01 14:56 ` Arthur Cohen [this message]
2024-08-01 14:56 ` [PATCH 032/125] gccrs: lower: Add base for lowering FormatArgs nodes Arthur Cohen
2024-08-01 14:56 ` [PATCH 033/125] gccrs: format-args: Add documentation for future expansion of function Arthur Cohen
2024-08-01 14:56 ` [PATCH 034/125] gccrs: Add error emitting when we can't resolve id expr Arthur Cohen
2024-08-01 14:56 ` [PATCH 035/125] gccrs: Add curly brackets, formatted clang Arthur Cohen
2024-08-01 14:56 ` [PATCH 036/125] gccrs: Ensure TupleStructPattern and TuplePattern have items Arthur Cohen
2024-08-01 14:56 ` [PATCH 037/125] gccrs: Clean BiMap to use tl::optional for lookups Arthur Cohen
2024-08-01 14:56 ` [PATCH 038/125] gccrs: Add support for external functions Arthur Cohen
2024-08-01 14:56 ` [PATCH 039/125] gccrs: Add get_pattern_kind to Pattern Arthur Cohen
2024-08-01 14:56 ` [PATCH 040/125] gccrs: Unify ASTValidation::visit for ExternalFunctionItem and Function Arthur Cohen
2024-08-01 14:56 ` [PATCH 041/125] gccrs: Update resolver to use `AST::Function` instead of `AST::ExternalFunctionItem` Arthur Cohen
2024-08-01 14:56 ` [PATCH 042/125] gccrs: Remove dead code associated with `AST::ExternalFunctionItem` Arthur Cohen
2024-08-01 14:56 ` [PATCH 043/125] gccrs: Placate clang-format re 'gcc/rust/backend/rust-tree.cc' Arthur Cohen
2024-08-01 14:56 ` [PATCH 044/125] gccrs: Replace reference to unique pointer with reference Arthur Cohen
2024-08-01 14:56 ` [PATCH 045/125] gccrs: Replace unique_ptr references with references Arthur Cohen
2024-08-01 14:56 ` [PATCH 046/125] gccrs: macro: Use MacroInvocation's node_id in ExternalItem constructor Arthur Cohen
2024-08-01 14:56 ` [PATCH 047/125] gccrs: format-args: Add base for expanding FormatArgs nodes Arthur Cohen
2024-08-01 14:56 ` [PATCH 048/125] gccrs: format-args: Start storing string in Rust memory Arthur Cohen
2024-11-23 20:17   ` Rust: Work around 'error[E0599]: no method named `leak` found for struct `std::string::String` in the current scope' (was: [PATCH 048/125] gccrs: format-args: Start storing string in Rust memory) Thomas Schwinge
2024-08-01 14:56 ` [PATCH 049/125] gccrs: format-args: Add basic expansion of unnamed Display::fmt arguments Arthur Cohen
2024-08-01 14:56 ` [PATCH 050/125] gccrs: format-args: Add basic test case Arthur Cohen
2024-08-01 14:56 ` [PATCH 051/125] gccrs: format-args: Only pass the format string to the parser Arthur Cohen
2024-08-01 14:56 ` [PATCH 052/125] gccrs: TyTy: add common SubstitutionRef API Arthur Cohen
2024-08-01 14:56 ` [PATCH 053/125] gccrs: TyTy: Variance analysis module Arthur Cohen
2024-08-01 14:56 ` [PATCH 054/125] gccrs: TyTy: Collect variance info from types Arthur Cohen
2024-08-01 14:56 ` [PATCH 055/125] gccrs: Store visibility properly in ExternalTypeItem Arthur Cohen
2024-08-01 14:56 ` [PATCH 056/125] gccrs: Fix typo Arthur Cohen
2024-08-01 14:56 ` [PATCH 057/125] gccrs: Split up rust-macro-builtins.cc Arthur Cohen
2024-08-01 14:56 ` [PATCH 058/125] gccrs: Placate clang-format re 'gcc/rust/lex/rust-lex.cc' Arthur Cohen
2024-08-01 14:56 ` [PATCH 059/125] gccrs: nr2.0: Add new ImmutableNameResolutionCtx class Arthur Cohen
2024-08-01 14:56 ` [PATCH 060/125] gccrs: sesh: Add late name resolution 2.0 Arthur Cohen
2024-08-01 14:56 ` [PATCH 061/125] gccrs: session-manager: Dump name resolution pass Arthur Cohen
2024-08-01 14:56 ` [PATCH 062/125] gccrs: session manager: Init Immutable name resolver Arthur Cohen
2024-08-01 14:56 ` [PATCH 063/125] gccrs: nr2.0: Add lookup of resolved nodes Arthur Cohen
2024-08-01 14:57 ` [PATCH 064/125] gccrs: typecheck: Start using nr2.0 properly Arthur Cohen
2024-08-01 14:57 ` [PATCH 065/125] gccrs: backend: Use new name resolver where necessary Arthur Cohen
2024-08-01 14:57 ` [PATCH 066/125] gccrs: nr2.0: Start using newtype pattern for Usage and Declaration Arthur Cohen
2024-08-01 14:57 ` [PATCH 067/125] gccrs: late: Setup builtin types properly, change Rib API Arthur Cohen
2024-08-01 14:57 ` [PATCH 068/125] gccrs: Fix duplicate detection Arthur Cohen
2024-08-01 14:57 ` [PATCH 069/125] gccrs: Emit error on identical use declarations Arthur Cohen
2024-08-01 14:57 ` [PATCH 070/125] gccrs: Change error message on unresolved import Arthur Cohen
2024-08-01 14:57 ` [PATCH 071/125] gccrs: Prevent error emission on resolver reentry Arthur Cohen
2024-08-01 14:57 ` [PATCH 072/125] gccrs: late: Add bool builtin type Arthur Cohen
2024-08-01 14:57 ` [PATCH 073/125] gccrs: Add modules to type namespace Arthur Cohen
2024-08-01 14:57 ` [PATCH 074/125] gccrs: Add name resolution for on globbing use decl Arthur Cohen
2024-08-01 14:57 ` [PATCH 075/125] gccrs: Shape up name resolver for normal direct calls Arthur Cohen
2024-08-01 14:57 ` [PATCH 076/125] gccrs: Add call to globbing visitor Arthur Cohen
2024-08-01 14:57 ` [PATCH 077/125] gccrs: Make globbing definition shadowable by default Arthur Cohen
2024-08-01 14:57 ` [PATCH 078/125] gccrs: Add support for ambiguous use declarations Arthur Cohen
2024-08-01 14:57 ` [PATCH 079/125] gccrs: Add tuple struct constructor to value namespace Arthur Cohen
2024-08-01 14:57 ` [PATCH 080/125] gccrs: Change error message to match test Arthur Cohen
2024-08-01 14:57 ` [PATCH 081/125] gccrs: Visit function return type in default resolver Arthur Cohen
2024-08-01 14:57 ` [PATCH 082/125] gccrs: Visit constant item " Arthur Cohen
2024-08-01 14:57 ` [PATCH 083/125] gccrs: Raw pointer type visitor didn't require overload Arthur Cohen
2024-08-01 14:57 ` [PATCH 084/125] gccrs: Values shall be inserted in the value namespace Arthur Cohen
2024-08-01 14:57 ` [PATCH 085/125] gccrs: Unit struct constructor shall be resolved Arthur Cohen
2024-08-01 14:57 ` [PATCH 086/125] gccrs: Add tuple struct to the type namespace Arthur Cohen
2024-08-01 14:57 ` [PATCH 087/125] gccrs: Change enum namespace from value to type Arthur Cohen
2024-08-01 14:57 ` [PATCH 088/125] gccrs: Struct are types, not values Arthur Cohen
2024-08-01 14:57 ` [PATCH 089/125] gccrs: Add constant identifiers to the value namespace Arthur Cohen
2024-08-01 14:57 ` [PATCH 090/125] gccrs: Remove extern block scoping Arthur Cohen
2024-08-01 14:57 ` [PATCH 091/125] gccrs: Remove unsafe block empty visit function Arthur Cohen
2024-08-01 14:57 ` [PATCH 092/125] gccrs: Use new name resolver to compile constant items Arthur Cohen
2024-08-01 14:57 ` [PATCH 093/125] gccrs: Reinject Self parameter in new resolver Arthur Cohen
2024-08-01 14:57 ` [PATCH 094/125] gccrs: Update assignment operator with cratenum Arthur Cohen
2024-08-01 14:57 ` [PATCH 095/125] gccrs: Prevent getting immutable context with classic nr Arthur Cohen
2024-08-01 14:57 ` [PATCH 096/125] gccrs: Fix quoted string format Arthur Cohen
2024-08-01 14:57 ` [PATCH 097/125] gccrs: Add mappings for struct base and struct fields Arthur Cohen
2024-08-01 14:57 ` [PATCH 098/125] gccrs: Fix use rebind name resolution Arthur Cohen
2024-08-01 14:57 ` [PATCH 099/125] gccrs: compile: resolve-path-ref: properly resolve nodeId with nr2.0 Arthur Cohen
2024-08-01 14:57 ` [PATCH 100/125] gccrs: nr2.0: Add new test cases Arthur Cohen
2024-08-01 14:57 ` [PATCH 101/125] gccrs: Add globbing name resolution 2.0 test Arthur Cohen
2024-08-01 14:57 ` [PATCH 102/125] gccrs: Change dfs function return type to support gcc 4.8 Arthur Cohen
2024-08-01 14:57 ` [PATCH 103/125] gccrs: Improve parsing of raw byte string literals Arthur Cohen
2024-08-01 14:57 ` [PATCH 104/125] gccrs: Recognize rustc_deprecated as a builtin attribute Arthur Cohen
2024-08-01 14:57 ` [PATCH 105/125] gccrs: Recognize unstable " Arthur Cohen
2024-08-01 14:57 ` [PATCH 106/125] gccrs: Avoid parsing const unsafe/extern functions as async Arthur Cohen
2024-08-01 14:57 ` [PATCH 107/125] gccrs: Improve parsing of raw string literals Arthur Cohen
2024-08-01 14:57 ` [PATCH 108/125] gccrs: raw-strings: Remove dg-excess-error directive Arthur Cohen
2024-08-01 14:57 ` [PATCH 109/125] gccrs: unify: Always coerce `!` to the target type Arthur Cohen
2024-08-01 14:57 ` [PATCH 110/125] gccrs: borrowck: Use rust-system.h Arthur Cohen
2024-08-01 14:57 ` [PATCH 111/125] gccrs: borrowck: Unify BIR terminilogy (node->statement) Arthur Cohen
2024-08-01 14:57 ` [PATCH 112/125] gccrs: borrowck: BIR: use callable API Arthur Cohen
2024-08-01 14:57 ` [PATCH 113/125] gccrs: borrowck: BIR: Place tree traverse API Arthur Cohen
2024-08-01 14:57 ` [PATCH 114/125] gccrs: borrowck: BIR: scope handling Arthur Cohen
2024-08-01 14:57 ` [PATCH 115/125] gccrs: borrowck: BIR: emit moves Arthur Cohen
2024-08-01 14:57 ` [PATCH 116/125] gccrs: borrowck: BIR: make BIR visitor const Arthur Cohen
2024-08-01 14:57 ` [PATCH 117/125] gccrs: borrowck: Polonius FFI Arthur Cohen
2024-08-01 14:57 ` [PATCH 118/125] gccrs: borrowck: Free region representation Arthur Cohen
2024-08-01 14:57 ` [PATCH 119/125] gccrs: borrowck: extract regions from types using VA Arthur Cohen
2024-08-01 14:57 ` [PATCH 120/125] gccrs: borrowck: Regions in BIR Arthur Cohen
2024-08-01 14:57 ` [PATCH 121/125] gccrs: borrowck: Fact collector Arthur Cohen
2024-08-01 14:57 ` [PATCH 122/125] gccrs: borrowck: Remove block braces to satisfy GNU style Arthur Cohen
2024-08-01 14:57 ` [PATCH 123/125] gccrs: borrowck: Bump copyright notice Arthur Cohen
2024-08-01 14:58 ` [PATCH 124/125] gccrs: Visit type during resolution of inherent impl Arthur Cohen
2024-08-01 14:58 ` [PATCH 125/125] gccrs: Add a test for inherent impl type name resolve Arthur Cohen

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20240801145809.366388-33-arthur.cohen@embecosm.com \
    --to=arthur.cohen@embecosm.com \
    --cc=gcc-patches@gcc.gnu.org \
    --cc=gcc-rust@gcc.gnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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).