]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
ast: Add base nodes for FormatArgs
authorArthur Cohen <arthur.cohen@embecosm.com>
Thu, 15 Feb 2024 19:58:48 +0000 (20:58 +0100)
committerCohenArthur <arthur.cohen@embecosm.com>
Fri, 1 Mar 2024 15:42:36 +0000 (15:42 +0000)
This commit adds a base for creating AST FormatArgs nodes after expanding
invocations of `format_args!()`. These nodes will then be expanded to
the proper runtime function calls (to core::fmt::rt) during the AST
lowering.

gcc/rust/ChangeLog:

* ast/rust-builtin-ast-nodes.h: New file.
* ast/rust-ast-full-decls.h (class FormatArgs): Declare new class.
* ast/rust-ast-collector.cc: Handle FormatArgs nodes properly.
* ast/rust-ast-collector.h: Likewise.
* ast/rust-ast-full.h: Likewise.
* ast/rust-ast-visitor.cc: Likewise.
* ast/rust-ast-visitor.h: Likewise.
* ast/rust-ast.cc: Likewise.
* ast/rust-ast.h: Likewise.
* expand/rust-derive.h: Likewise.
* hir/rust-ast-lower-base.cc: Likewise.
* hir/rust-ast-lower-base.h: Likewise.
* hir/rust-ast-lower-expr.cc: Likewise.
* hir/rust-ast-lower-expr.h: Likewise.
* resolve/rust-ast-resolve-base.cc: Likewise.
* resolve/rust-ast-resolve-base.h: Likewise.

16 files changed:
gcc/rust/ast/rust-ast-collector.cc
gcc/rust/ast/rust-ast-collector.h
gcc/rust/ast/rust-ast-full-decls.h
gcc/rust/ast/rust-ast-full.h
gcc/rust/ast/rust-ast-visitor.cc
gcc/rust/ast/rust-ast-visitor.h
gcc/rust/ast/rust-ast.cc
gcc/rust/ast/rust-ast.h
gcc/rust/ast/rust-builtin-ast-nodes.h [new file with mode: 0644]
gcc/rust/expand/rust-derive.h
gcc/rust/hir/rust-ast-lower-base.cc
gcc/rust/hir/rust-ast-lower-base.h
gcc/rust/hir/rust-ast-lower-expr.cc
gcc/rust/hir/rust-ast-lower-expr.h
gcc/rust/resolve/rust-ast-resolve-base.cc
gcc/rust/resolve/rust-ast-resolve-base.h

index 181f1b100be9cc0b16ec121bbc5acba415d9bfc5..b8ec62367bcf69e4bfc42037e963b883e213e15b 100644 (file)
@@ -16,6 +16,8 @@
 // along with GCC; see the file COPYING3.  If not see
 // <http://www.gnu.org/licenses/>.
 #include "rust-ast-collector.h"
+#include "rust-ast.h"
+#include "rust-diagnostics.h"
 #include "rust-item.h"
 #include "rust-keyword-values.h"
 
@@ -2805,5 +2807,11 @@ TokenCollector::visit (BareFunctionType &type)
     }
 }
 
+void
+TokenCollector::visit (AST::FormatArgs &fmt)
+{
+  rust_sorry_at (0, "unimplemented format_args!() visitor");
+}
+
 } // namespace AST
 } // namespace Rust
index cf97c185a26fbbfe8e0f9c1132018555b3165eb0..ec695ef5b314a8ccf474cab7b402bfddeed95202 100644 (file)
@@ -398,6 +398,8 @@ public:
   void visit (SliceType &type);
   void visit (InferredType &type);
   void visit (BareFunctionType &type);
+
+  void visit (FormatArgs &fmt);
 };
 } // namespace AST
 
index c96bbfb07d96ed4393131384c3a8ff2a471876eb..8d5c8dbc8213ecf6083290b42a90e4f85f527658 100644 (file)
@@ -267,6 +267,9 @@ class SliceType;
 class InferredType;
 struct MaybeNamedParam;
 class BareFunctionType;
+
+// rust-builtin-ast-nodes.h
+class FormatArgs;
 } // namespace AST
 } // namespace Rust
 
index f2152193a135e0adc24b2605a90a0f22f79404da..ebd38f2520c42ecb6752b36938a822b59b41e8f5 100644 (file)
@@ -28,5 +28,6 @@
 #include "rust-stmt.h"
 #include "rust-type.h"
 #include "rust-macro.h"
+#include "rust-builtin-ast-nodes.h"
 
 #endif
index 27b9aa47d99c2895b6247109bf4891ca1af9257d..c72e2d72f6d2e18cd77945ad4f4dc4ceeaaa0f7e 100644 (file)
@@ -1395,6 +1395,12 @@ DefaultASTVisitor::visit (AST::BareFunctionType &type)
     visit (type.get_return_type ());
 }
 
+void
+DefaultASTVisitor::visit (AST::FormatArgs &)
+{
+  // FIXME: Do we have anything to do? any subnodes to visit? Probably, right?
+}
+
 void
 DefaultASTVisitor::visit (AST::VariadicParam &param)
 {
index 6c9715eb07752f4f9d4c5d946e20613d4e0cd2d6..c5c9a025ba6ee72475114e6069d11e9bde3db5e1 100644 (file)
@@ -229,6 +229,9 @@ public:
   virtual void visit (InferredType &type) = 0;
   virtual void visit (BareFunctionType &type) = 0;
 
+  // special AST nodes for certain builtin macros such as `asm!()`
+  virtual void visit (FormatArgs &fmt) = 0;
+
   // TODO: rust-cond-compilation.h visiting? not currently used
 };
 
@@ -390,6 +393,7 @@ protected:
   virtual void visit (AST::SelfParam &self) override;
   virtual void visit (AST::FunctionParam &param) override;
   virtual void visit (AST::VariadicParam &param) override;
+  virtual void visit (AST::FormatArgs &fmt) override;
 
   template <typename T> void visit (T &node) { node.accept_vis (*this); }
 
@@ -422,6 +426,7 @@ protected:
   virtual void visit (AST::MacroTranscriber &transcriber);
   virtual void visit (AST::StructPatternElements &spe);
   virtual void visit (AST::MaybeNamedParam &param);
+
   void visit (AST::Attribute &attribute) {}
 
   template <typename T> void visit_outer_attrs (T &node)
index 90fe92694045d69ac92f5adc4aec325955b568b6..5d571b466222a37b6ea53771cb2e6693e280edf9 100644 (file)
@@ -5048,6 +5048,12 @@ MetaWord::accept_vis (ASTVisitor &vis)
   vis.visit (*this);
 }
 
+void
+FormatArgs::accept_vis (ASTVisitor &vis)
+{
+  vis.visit (*this);
+}
+
 } // namespace AST
 
 std::ostream &
index 1422d77eade4c1262dd3b1509cef7f8a5408331f..c4d5858dd636df899e076b9ffa69b0efff7b518f 100644 (file)
@@ -2029,6 +2029,7 @@ public:
 class PathExpr : public ExprWithoutBlock
 {
 };
+
 } // namespace AST
 } // namespace Rust
 
diff --git a/gcc/rust/ast/rust-builtin-ast-nodes.h b/gcc/rust/ast/rust-builtin-ast-nodes.h
new file mode 100644 (file)
index 0000000..3998fbf
--- /dev/null
@@ -0,0 +1,129 @@
+// Copyright (C) 2024 Free Software Foundation, Inc.
+
+// This file is part of GCC.
+
+// GCC is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 3, or (at your option) any later
+// version.
+
+// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+// for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with GCC; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+#ifndef RUST_AST_BUILTIN_NODES_H
+#define RUST_AST_BUILTIN_NODES_H
+
+#include "rust-system.h"
+#include "line-map.h"
+#include "optional.h"
+#include "rust-ast.h"
+#include "rust-fmt.h"
+
+namespace Rust {
+namespace AST {
+
+// Definitions, from rustc's `FormatArgs` AST struct
+// https://github.com/rust-lang/rust/blob/1be468815c/compiler/rustc_ast/src/format.rs
+//
+// format_args!("hello {abc:.xyz$}!!", abc="world");
+// └──────────────────────────────────────────────┘
+//                     FormatArgs
+//
+// format_args!("hello {abc:.xyz$}!!", abc="world");
+//                                     └─────────┘
+//                                      argument
+//
+// format_args!("hello {abc:.xyz$}!!", abc="world");
+//              └───────────────────┘
+//                     template
+//
+// format_args!("hello {abc:.xyz$}!!", abc="world");
+//               └────┘└─────────┘└┘
+//                      pieces
+//
+// format_args!("hello {abc:.xyz$}!!", abc="world");
+//               └────┘           └┘
+//                   literal pieces
+//
+// format_args!("hello {abc:.xyz$}!!", abc="world");
+//                     └─────────┘
+//                     placeholder
+//
+// format_args!("hello {abc:.xyz$}!!", abc="world");
+//                      └─┘  └─┘
+//                      positions (could be names, numbers, empty, or `*`)
+
+class FormatArgumentKind
+{
+public:
+  Identifier &get_ident ()
+  {
+    rust_assert (kind == Kind::Captured || kind == Kind::Named);
+
+    return ident.value ();
+  }
+
+private:
+  enum class Kind
+  {
+    Normal,
+    Named,
+    Captured,
+  } kind;
+
+  tl::optional<Identifier> ident;
+};
+
+class FormatArgument
+{
+  FormatArgumentKind kind;
+  std::unique_ptr<Expr> expr;
+};
+
+class FormatArguments
+{
+  std::vector<FormatArgument> args;
+};
+
+// TODO: Format documentation better
+// Having a separate AST node for `format_args!()` expansion allows some
+// important optimizations which help reduce generated code a lot. For example,
+// turning `format_args!("a {} {} {}", 15, "hey", 'a')` directly into
+// `format_args!("a 15 hey a")`, since all arguments are literals. Or,
+// flattening imbricated `format_args!()` calls: `format_args!("heyo {}",
+// format_args!("result: {}", some_result))` -> `format_args!("heyo result: {}",
+// some_result)`
+// FIXME: Move to rust-macro.h
+class FormatArgs : public Visitable
+{
+public:
+  enum class Newline
+  {
+    Yes,
+    No
+  };
+
+  FormatArgs (location_t loc, Fmt::PieceSlice template_str,
+             FormatArguments arguments)
+    : loc (loc), template_str (std::move (template_str)),
+      arguments (std::move (arguments))
+  {}
+
+  void accept_vis (AST::ASTVisitor &vis);
+
+private:
+  location_t loc;
+  Fmt::PieceSlice template_str;
+  FormatArguments arguments;
+};
+
+} // namespace AST
+} // namespace Rust
+
+#endif // ! RUST_AST_BUILTIN_NODES_H
index 8fe29c0db75c50f921a4169e81435c925dbc8e00..f953c3decbfa1ea32967549cb1552e90e5fd5d2c 100644 (file)
@@ -221,6 +221,7 @@ private:
   virtual void visit (SelfParam &param) override final{};
   virtual void visit (FunctionParam &param) override final{};
   virtual void visit (VariadicParam &param) override final{};
+  virtual void visit (FormatArgs &param) override final{};
 };
 
 } // namespace AST
index bcc4797df77729a9fbcb8742fcbf8883dd70a27c..fa37d62d02608e35dc589bee54060cff036c9434 100644 (file)
@@ -20,6 +20,7 @@
 #include "rust-ast-lower-type.h"
 #include "rust-ast-lower-pattern.h"
 #include "rust-ast-lower-extern.h"
+#include "rust-ast.h"
 #include "rust-attribute-values.h"
 #include "rust-item.h"
 #include "rust-system.h"
@@ -523,6 +524,10 @@ void
 ASTLoweringBase::visit (AST::SelfParam &param)
 {}
 
+void
+ASTLoweringBase::visit (AST::FormatArgs &fmt)
+{}
+
 HIR::Lifetime
 ASTLoweringBase::lower_lifetime (AST::Lifetime &lifetime,
                                 bool default_to_static_lifetime)
index d7b94ac8a700cb9f184a9faf147afd143b36b4e5..7b0ce375f8329a142611a64dcfccc0cadc6ffd0c 100644 (file)
@@ -19,6 +19,7 @@
 #ifndef RUST_AST_LOWER_BASE
 #define RUST_AST_LOWER_BASE
 
+#include "rust-ast.h"
 #include "rust-system.h"
 #include "rust-ast-full.h"
 #include "rust-ast-visitor.h"
@@ -253,6 +254,8 @@ public:
   virtual void visit (AST::VariadicParam &param);
   virtual void visit (AST::SelfParam &param);
 
+  virtual void visit (AST::FormatArgs &fmt);
+
 protected:
   ASTLoweringBase ()
     : mappings (Analysis::Mappings::get ()),
index 35deb57abe6d8558842ad5402d47469509128160..8e07b19df4c870fa0ee8dac9cd1f6044feae0626 100644 (file)
@@ -22,6 +22,8 @@
 #include "rust-ast-lower-struct-field-expr.h"
 #include "rust-ast-lower-pattern.h"
 #include "rust-ast-lower-type.h"
+#include "rust-ast.h"
+#include "rust-diagnostics.h"
 
 namespace Rust {
 namespace HIR {
@@ -828,5 +830,11 @@ ASTLoweringExpr::visit (AST::ClosureExprInnerTyped &expr)
                            expr.get_locus ());
 }
 
+void
+ASTLoweringExpr::visit (AST::FormatArgs &fmt)
+{
+  rust_sorry_at (0, "unimplemented format_args!() visitor");
+}
+
 } // namespace HIR
 } // namespace Rust
index 56da9d1ab88733fdba05858e705fbb0705846b17..168dd0140020b217e09763fa25c005e360f3b52e 100644 (file)
@@ -20,6 +20,7 @@
 #define RUST_AST_LOWER_EXPR
 
 #include "rust-ast-lower-base.h"
+#include "rust-ast.h"
 
 namespace Rust {
 namespace HIR {
@@ -121,6 +122,9 @@ public:
   void visit (AST::ClosureExprInner &expr) override;
   void visit (AST::ClosureExprInnerTyped &expr) override;
 
+  // Extra visitor for FormatArgs nodes
+  void visit (AST::FormatArgs &fmt) override;
+
 private:
   ASTLoweringExpr ();
 
index c88bd58860ab15f7798032e40504ebf3d80bf8f2..04a0bb65ec2adb4c528b932c7acb356a00dae709 100644 (file)
@@ -650,5 +650,11 @@ void
 ResolverBase::visit (AST::FunctionParam &)
 {}
 
+void
+ResolverBase::visit (AST::FormatArgs &fmt)
+{
+  rust_sorry_at (0, "unimplemented format_args!() visitor");
+}
+
 } // namespace Resolver
 } // namespace Rust
index 9bc64331f5a9e73aa8594b4cdf94116e305bfe2b..3b4d28618e4048420d747a276dba70a9fd644db1 100644 (file)
@@ -20,6 +20,7 @@
 #define RUST_AST_RESOLVE_BASE_H
 
 #include "rust-ast-visitor.h"
+#include "rust-ast.h"
 #include "rust-name-resolver.h"
 #include "rust-diagnostics.h"
 #include "rust-location.h"
@@ -198,6 +199,8 @@ public:
   void visit (AST::VariadicParam &param);
   void visit (AST::SelfParam &param);
 
+  void visit (AST::FormatArgs &fmt);
+
 protected:
   ResolverBase ()
     : resolver (Resolver::get ()), mappings (Analysis::Mappings::get ()),