aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorArthur Cohen <arthur.cohen@embecosm.com>2024-02-15 20:58:48 +0100
committerCohenArthur <arthur.cohen@embecosm.com>2024-03-01 15:42:36 +0000
commit12ca8dbb4bc22da1b93630c884b75ce254605882 (patch)
treedabaaeac068924aa1d6520bbe3aad26ad196e905
parent7064be37a38b4c3c8ad8193e13312e2c558303dc (diff)
downloadgcc-12ca8dbb4bc22da1b93630c884b75ce254605882.zip
gcc-12ca8dbb4bc22da1b93630c884b75ce254605882.tar.gz
gcc-12ca8dbb4bc22da1b93630c884b75ce254605882.tar.bz2
ast: Add base nodes for FormatArgs
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.
-rw-r--r--gcc/rust/ast/rust-ast-collector.cc8
-rw-r--r--gcc/rust/ast/rust-ast-collector.h2
-rw-r--r--gcc/rust/ast/rust-ast-full-decls.h3
-rw-r--r--gcc/rust/ast/rust-ast-full.h1
-rw-r--r--gcc/rust/ast/rust-ast-visitor.cc6
-rw-r--r--gcc/rust/ast/rust-ast-visitor.h5
-rw-r--r--gcc/rust/ast/rust-ast.cc6
-rw-r--r--gcc/rust/ast/rust-ast.h1
-rw-r--r--gcc/rust/ast/rust-builtin-ast-nodes.h129
-rw-r--r--gcc/rust/expand/rust-derive.h1
-rw-r--r--gcc/rust/hir/rust-ast-lower-base.cc5
-rw-r--r--gcc/rust/hir/rust-ast-lower-base.h3
-rw-r--r--gcc/rust/hir/rust-ast-lower-expr.cc8
-rw-r--r--gcc/rust/hir/rust-ast-lower-expr.h4
-rw-r--r--gcc/rust/resolve/rust-ast-resolve-base.cc6
-rw-r--r--gcc/rust/resolve/rust-ast-resolve-base.h3
16 files changed, 191 insertions, 0 deletions
diff --git a/gcc/rust/ast/rust-ast-collector.cc b/gcc/rust/ast/rust-ast-collector.cc
index 181f1b1..b8ec623 100644
--- a/gcc/rust/ast/rust-ast-collector.cc
+++ b/gcc/rust/ast/rust-ast-collector.cc
@@ -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
diff --git a/gcc/rust/ast/rust-ast-collector.h b/gcc/rust/ast/rust-ast-collector.h
index cf97c18..ec695ef 100644
--- a/gcc/rust/ast/rust-ast-collector.h
+++ b/gcc/rust/ast/rust-ast-collector.h
@@ -398,6 +398,8 @@ public:
void visit (SliceType &type);
void visit (InferredType &type);
void visit (BareFunctionType &type);
+
+ void visit (FormatArgs &fmt);
};
} // namespace AST
diff --git a/gcc/rust/ast/rust-ast-full-decls.h b/gcc/rust/ast/rust-ast-full-decls.h
index c96bbfb..8d5c8db 100644
--- a/gcc/rust/ast/rust-ast-full-decls.h
+++ b/gcc/rust/ast/rust-ast-full-decls.h
@@ -267,6 +267,9 @@ class SliceType;
class InferredType;
struct MaybeNamedParam;
class BareFunctionType;
+
+// rust-builtin-ast-nodes.h
+class FormatArgs;
} // namespace AST
} // namespace Rust
diff --git a/gcc/rust/ast/rust-ast-full.h b/gcc/rust/ast/rust-ast-full.h
index f215219..ebd38f2 100644
--- a/gcc/rust/ast/rust-ast-full.h
+++ b/gcc/rust/ast/rust-ast-full.h
@@ -28,5 +28,6 @@
#include "rust-stmt.h"
#include "rust-type.h"
#include "rust-macro.h"
+#include "rust-builtin-ast-nodes.h"
#endif
diff --git a/gcc/rust/ast/rust-ast-visitor.cc b/gcc/rust/ast/rust-ast-visitor.cc
index 27b9aa4..c72e2d7 100644
--- a/gcc/rust/ast/rust-ast-visitor.cc
+++ b/gcc/rust/ast/rust-ast-visitor.cc
@@ -1396,6 +1396,12 @@ DefaultASTVisitor::visit (AST::BareFunctionType &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)
{
if (param.has_pattern ())
diff --git a/gcc/rust/ast/rust-ast-visitor.h b/gcc/rust/ast/rust-ast-visitor.h
index 6c9715e..c5c9a02 100644
--- a/gcc/rust/ast/rust-ast-visitor.h
+++ b/gcc/rust/ast/rust-ast-visitor.h
@@ -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)
diff --git a/gcc/rust/ast/rust-ast.cc b/gcc/rust/ast/rust-ast.cc
index 90fe926..5d571b4 100644
--- a/gcc/rust/ast/rust-ast.cc
+++ b/gcc/rust/ast/rust-ast.cc
@@ -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 &
diff --git a/gcc/rust/ast/rust-ast.h b/gcc/rust/ast/rust-ast.h
index 1422d77..c4d5858 100644
--- a/gcc/rust/ast/rust-ast.h
+++ b/gcc/rust/ast/rust-ast.h
@@ -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
index 0000000..3998fbf
--- /dev/null
+++ b/gcc/rust/ast/rust-builtin-ast-nodes.h
@@ -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
diff --git a/gcc/rust/expand/rust-derive.h b/gcc/rust/expand/rust-derive.h
index 8fe29c0..f953c3d 100644
--- a/gcc/rust/expand/rust-derive.h
+++ b/gcc/rust/expand/rust-derive.h
@@ -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
diff --git a/gcc/rust/hir/rust-ast-lower-base.cc b/gcc/rust/hir/rust-ast-lower-base.cc
index bcc4797..fa37d62 100644
--- a/gcc/rust/hir/rust-ast-lower-base.cc
+++ b/gcc/rust/hir/rust-ast-lower-base.cc
@@ -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)
diff --git a/gcc/rust/hir/rust-ast-lower-base.h b/gcc/rust/hir/rust-ast-lower-base.h
index d7b94ac..7b0ce37 100644
--- a/gcc/rust/hir/rust-ast-lower-base.h
+++ b/gcc/rust/hir/rust-ast-lower-base.h
@@ -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 ()),
diff --git a/gcc/rust/hir/rust-ast-lower-expr.cc b/gcc/rust/hir/rust-ast-lower-expr.cc
index 35deb57..8e07b19 100644
--- a/gcc/rust/hir/rust-ast-lower-expr.cc
+++ b/gcc/rust/hir/rust-ast-lower-expr.cc
@@ -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
diff --git a/gcc/rust/hir/rust-ast-lower-expr.h b/gcc/rust/hir/rust-ast-lower-expr.h
index 56da9d1..168dd01 100644
--- a/gcc/rust/hir/rust-ast-lower-expr.h
+++ b/gcc/rust/hir/rust-ast-lower-expr.h
@@ -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 ();
diff --git a/gcc/rust/resolve/rust-ast-resolve-base.cc b/gcc/rust/resolve/rust-ast-resolve-base.cc
index c88bd58..04a0bb6 100644
--- a/gcc/rust/resolve/rust-ast-resolve-base.cc
+++ b/gcc/rust/resolve/rust-ast-resolve-base.cc
@@ -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
diff --git a/gcc/rust/resolve/rust-ast-resolve-base.h b/gcc/rust/resolve/rust-ast-resolve-base.h
index 9bc6433..3b4d286 100644
--- a/gcc/rust/resolve/rust-ast-resolve-base.h
+++ b/gcc/rust/resolve/rust-ast-resolve-base.h
@@ -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 ()),