aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorbors[bot] <26634292+bors[bot]@users.noreply.github.com>2022-02-23 13:37:07 +0000
committerGitHub <noreply@github.com>2022-02-23 13:37:07 +0000
commitbf92a1012264f2544e73a7a8dd0ac1e473c7f658 (patch)
treef7a3fd3afb0c2e2b2678d80dcd742da23c1b8f9a /gcc
parent10de9cf4f3765526a1a82a4a7d14908b58c6538c (diff)
parent48b3fe622e9a582b076c6f4b19b5e8b69891ac31 (diff)
downloadgcc-bf92a1012264f2544e73a7a8dd0ac1e473c7f658.zip
gcc-bf92a1012264f2544e73a7a8dd0ac1e473c7f658.tar.gz
gcc-bf92a1012264f2544e73a7a8dd0ac1e473c7f658.tar.bz2
Merge #969
969: Add builtin macros framework r=CohenArthur a=CohenArthur This PR adds bases to define new builtin macro functions. Since we operate at the `insert_macro_def` level, this requires builtin macros to be defined, as is the case in the rust standard library: ```rust macro_rules! assert { ($cond:expr $(,)?) => {{ /* compiler built-in */ }}; ($cond:expr, $($arg:tt)+) => {{ /* compiler built-in */ }}; } ``` Co-authored-by: Arthur Cohen <arthur.cohen@embecosm.com>
Diffstat (limited to 'gcc')
-rw-r--r--gcc/rust/Make-lang.in1
-rw-r--r--gcc/rust/ast/rust-macro.h45
-rw-r--r--gcc/rust/expand/rust-macro-builtins.cc30
-rw-r--r--gcc/rust/expand/rust-macro-builtins.h34
-rw-r--r--gcc/rust/expand/rust-macro-expand.cc20
-rw-r--r--gcc/rust/util/rust-hir-map.cc11
6 files changed, 135 insertions, 6 deletions
diff --git a/gcc/rust/Make-lang.in b/gcc/rust/Make-lang.in
index 080b9dd..9de93fe 100644
--- a/gcc/rust/Make-lang.in
+++ b/gcc/rust/Make-lang.in
@@ -75,6 +75,7 @@ GRS_OBJS = \
rust/rust-compile-resolve-path.o \
rust/rust-macro-expand.o \
rust/rust-macro-invoc-lexer.o \
+ rust/rust-macro-builtins.o \
rust/rust-hir-full-test.o \
rust/rust-hir-map.o \
rust/rust-attributes.o \
diff --git a/gcc/rust/ast/rust-macro.h b/gcc/rust/ast/rust-macro.h
index 995b255..9f8f19c 100644
--- a/gcc/rust/ast/rust-macro.h
+++ b/gcc/rust/ast/rust-macro.h
@@ -361,9 +361,26 @@ class MacroRulesDefinition : public MacroItem
DelimType delim_type;
// MacroRules rules;
std::vector<MacroRule> rules; // inlined form
-
Location locus;
+ std::function<ASTFragment (Location, MacroInvocData &)>
+ associated_transcriber;
+ // Since we can't compare std::functions, we need to use an extra boolean
+ bool is_builtin_rule;
+
+ /**
+ * Default function to use as an associated transcriber. This function should
+ * never be called, hence the gcc_unreachable().
+ * If this function is used, then the macro is not builtin and the compiler
+ * should make use of the actual rules. If the macro is builtin, then another
+ * associated transcriber should be used
+ */
+ static ASTFragment dummy_builtin (Location, MacroInvocData &)
+ {
+ gcc_unreachable ();
+ return ASTFragment::create_empty ();
+ }
+
/* NOTE: in rustc, macro definitions are considered (and parsed as) a type
* of macro, whereas here they are considered part of the language itself.
* I am not aware of the implications of this decision. The rustc spec does
@@ -377,7 +394,17 @@ public:
std::vector<MacroRule> rules,
std::vector<Attribute> outer_attrs, Location locus)
: outer_attrs (std::move (outer_attrs)), rule_name (std::move (rule_name)),
- delim_type (delim_type), rules (std::move (rules)), locus (locus)
+ delim_type (delim_type), rules (std::move (rules)), locus (locus),
+ associated_transcriber (dummy_builtin), is_builtin_rule (false)
+ {}
+
+ MacroRulesDefinition (Identifier builtin_name, DelimType delim_type,
+ std::function<ASTFragment (Location, MacroInvocData &)>
+ associated_transcriber)
+ : outer_attrs (std::vector<Attribute> ()), rule_name (builtin_name),
+ delim_type (delim_type), rules (std::vector<MacroRule> ()),
+ locus (Location ()), associated_transcriber (associated_transcriber),
+ is_builtin_rule (true)
{}
void accept_vis (ASTVisitor &vis) override;
@@ -400,6 +427,20 @@ public:
std::vector<MacroRule> &get_rules () { return rules; }
const std::vector<MacroRule> &get_rules () const { return rules; }
+ bool is_builtin () const { return is_builtin_rule; }
+ const std::function<ASTFragment (Location, MacroInvocData &)> &
+ get_builtin_transcriber () const
+ {
+ rust_assert (is_builtin ());
+ return associated_transcriber;
+ }
+ void set_builtin_transcriber (
+ std::function<ASTFragment (Location, MacroInvocData &)> transcriber)
+ {
+ associated_transcriber = transcriber;
+ is_builtin_rule = true;
+ }
+
protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
diff --git a/gcc/rust/expand/rust-macro-builtins.cc b/gcc/rust/expand/rust-macro-builtins.cc
new file mode 100644
index 0000000..b7bbd32
--- /dev/null
+++ b/gcc/rust/expand/rust-macro-builtins.cc
@@ -0,0 +1,30 @@
+// Copyright (C) 2020-2022 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/>.
+
+#include "rust-macro-builtins.h"
+#include "rust-diagnostics.h"
+
+namespace Rust {
+AST::ASTFragment
+MacroBuiltin::assert (Location invoc_locus, AST::MacroInvocData &invoc)
+{
+ rust_debug ("assert!() called");
+
+ return AST::ASTFragment::create_empty ();
+}
+} // namespace Rust
diff --git a/gcc/rust/expand/rust-macro-builtins.h b/gcc/rust/expand/rust-macro-builtins.h
new file mode 100644
index 0000000..f279d39
--- /dev/null
+++ b/gcc/rust/expand/rust-macro-builtins.h
@@ -0,0 +1,34 @@
+// Copyright (C) 2020-2022 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_MACRO_BUILTINS_H
+#define RUST_MACRO_BUILTINS_H
+
+#include "rust-ast.h"
+#include "rust-location.h"
+
+namespace Rust {
+class MacroBuiltin
+{
+public:
+ static AST::ASTFragment assert (Location invoc_locus,
+ AST::MacroInvocData &invoc);
+};
+} // namespace Rust
+
+#endif // RUST_MACRO_BUILTINS_H
diff --git a/gcc/rust/expand/rust-macro-expand.cc b/gcc/rust/expand/rust-macro-expand.cc
index b54aa01..7552e82 100644
--- a/gcc/rust/expand/rust-macro-expand.cc
+++ b/gcc/rust/expand/rust-macro-expand.cc
@@ -3194,8 +3194,14 @@ MacroExpander::expand_invoc (AST::MacroInvocation &invoc)
bool ok = mappings->lookup_macro_def (resolved_node, &rules_def);
rust_assert (ok);
- auto fragment
- = expand_decl_macro (invoc.get_locus (), invoc_data, *rules_def, false);
+ auto fragment = AST::ASTFragment::create_empty ();
+
+ if (rules_def->is_builtin ())
+ fragment
+ = rules_def->get_builtin_transcriber () (invoc.get_locus (), invoc_data);
+ else
+ fragment
+ = expand_decl_macro (invoc.get_locus (), invoc_data, *rules_def, false);
// lets attach this fragment to the invocation
invoc.set_fragment (std::move (fragment));
@@ -3229,8 +3235,14 @@ MacroExpander::expand_invoc_semi (AST::MacroInvocationSemi &invoc)
bool ok = mappings->lookup_macro_def (resolved_node, &rules_def);
rust_assert (ok);
- auto fragment
- = expand_decl_macro (invoc.get_locus (), invoc_data, *rules_def, true);
+ auto fragment = AST::ASTFragment::create_empty ();
+
+ if (rules_def->is_builtin ())
+ fragment
+ = rules_def->get_builtin_transcriber () (invoc.get_locus (), invoc_data);
+ else
+ fragment
+ = expand_decl_macro (invoc.get_locus (), invoc_data, *rules_def, true);
// lets attach this fragment to the invocation
invoc.set_fragment (std::move (fragment));
diff --git a/gcc/rust/util/rust-hir-map.cc b/gcc/rust/util/rust-hir-map.cc
index 1348e29..1c0e8fc 100644
--- a/gcc/rust/util/rust-hir-map.cc
+++ b/gcc/rust/util/rust-hir-map.cc
@@ -19,6 +19,7 @@
#include "rust-hir-map.h"
#include "rust-ast-full.h"
#include "rust-hir-full.h"
+#include "rust-macro-builtins.h"
namespace Rust {
namespace Analysis {
@@ -741,6 +742,16 @@ Mappings::iterate_trait_items (
void
Mappings::insert_macro_def (AST::MacroRulesDefinition *macro)
{
+ static std::map<std::string, std::function<AST::ASTFragment (
+ Location, AST::MacroInvocData &)>>
+ builtin_macros = {
+ {"assert", MacroBuiltin::assert},
+ };
+
+ auto builtin = builtin_macros.find (macro->get_rule_name ());
+ if (builtin != builtin_macros.end ())
+ macro->set_builtin_transcriber (builtin->second);
+
auto it = macroMappings.find (macro->get_node_id ());
rust_assert (it == macroMappings.end ());