Skip to content

Commit bf92a10

Browse files
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 <[email protected]>
2 parents 10de9cf + 48b3fe6 commit bf92a10

File tree

6 files changed

+135
-6
lines changed

6 files changed

+135
-6
lines changed

gcc/rust/Make-lang.in

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@ GRS_OBJS = \
7575
rust/rust-compile-resolve-path.o \
7676
rust/rust-macro-expand.o \
7777
rust/rust-macro-invoc-lexer.o \
78+
rust/rust-macro-builtins.o \
7879
rust/rust-hir-full-test.o \
7980
rust/rust-hir-map.o \
8081
rust/rust-attributes.o \

gcc/rust/ast/rust-macro.h

Lines changed: 43 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -361,9 +361,26 @@ class MacroRulesDefinition : public MacroItem
361361
DelimType delim_type;
362362
// MacroRules rules;
363363
std::vector<MacroRule> rules; // inlined form
364-
365364
Location locus;
366365

366+
std::function<ASTFragment (Location, MacroInvocData &)>
367+
associated_transcriber;
368+
// Since we can't compare std::functions, we need to use an extra boolean
369+
bool is_builtin_rule;
370+
371+
/**
372+
* Default function to use as an associated transcriber. This function should
373+
* never be called, hence the gcc_unreachable().
374+
* If this function is used, then the macro is not builtin and the compiler
375+
* should make use of the actual rules. If the macro is builtin, then another
376+
* associated transcriber should be used
377+
*/
378+
static ASTFragment dummy_builtin (Location, MacroInvocData &)
379+
{
380+
gcc_unreachable ();
381+
return ASTFragment::create_empty ();
382+
}
383+
367384
/* NOTE: in rustc, macro definitions are considered (and parsed as) a type
368385
* of macro, whereas here they are considered part of the language itself.
369386
* I am not aware of the implications of this decision. The rustc spec does
@@ -377,7 +394,17 @@ class MacroRulesDefinition : public MacroItem
377394
std::vector<MacroRule> rules,
378395
std::vector<Attribute> outer_attrs, Location locus)
379396
: outer_attrs (std::move (outer_attrs)), rule_name (std::move (rule_name)),
380-
delim_type (delim_type), rules (std::move (rules)), locus (locus)
397+
delim_type (delim_type), rules (std::move (rules)), locus (locus),
398+
associated_transcriber (dummy_builtin), is_builtin_rule (false)
399+
{}
400+
401+
MacroRulesDefinition (Identifier builtin_name, DelimType delim_type,
402+
std::function<ASTFragment (Location, MacroInvocData &)>
403+
associated_transcriber)
404+
: outer_attrs (std::vector<Attribute> ()), rule_name (builtin_name),
405+
delim_type (delim_type), rules (std::vector<MacroRule> ()),
406+
locus (Location ()), associated_transcriber (associated_transcriber),
407+
is_builtin_rule (true)
381408
{}
382409

383410
void accept_vis (ASTVisitor &vis) override;
@@ -400,6 +427,20 @@ class MacroRulesDefinition : public MacroItem
400427
std::vector<MacroRule> &get_rules () { return rules; }
401428
const std::vector<MacroRule> &get_rules () const { return rules; }
402429

430+
bool is_builtin () const { return is_builtin_rule; }
431+
const std::function<ASTFragment (Location, MacroInvocData &)> &
432+
get_builtin_transcriber () const
433+
{
434+
rust_assert (is_builtin ());
435+
return associated_transcriber;
436+
}
437+
void set_builtin_transcriber (
438+
std::function<ASTFragment (Location, MacroInvocData &)> transcriber)
439+
{
440+
associated_transcriber = transcriber;
441+
is_builtin_rule = true;
442+
}
443+
403444
protected:
404445
/* Use covariance to implement clone function as returning this object rather
405446
* than base */
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
// Copyright (C) 2020-2022 Free Software Foundation, Inc.
2+
3+
// This file is part of GCC.
4+
5+
// GCC is free software; you can redistribute it and/or modify it under
6+
// the terms of the GNU General Public License as published by the Free
7+
// Software Foundation; either version 3, or (at your option) any later
8+
// version.
9+
10+
// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
11+
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
12+
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13+
// for more details.
14+
15+
// You should have received a copy of the GNU General Public License
16+
// along with GCC; see the file COPYING3. If not see
17+
// <http://www.gnu.org/licenses/>.
18+
19+
#include "rust-macro-builtins.h"
20+
#include "rust-diagnostics.h"
21+
22+
namespace Rust {
23+
AST::ASTFragment
24+
MacroBuiltin::assert (Location invoc_locus, AST::MacroInvocData &invoc)
25+
{
26+
rust_debug ("assert!() called");
27+
28+
return AST::ASTFragment::create_empty ();
29+
}
30+
} // namespace Rust

gcc/rust/expand/rust-macro-builtins.h

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
// Copyright (C) 2020-2022 Free Software Foundation, Inc.
2+
3+
// This file is part of GCC.
4+
5+
// GCC is free software; you can redistribute it and/or modify it under
6+
// the terms of the GNU General Public License as published by the Free
7+
// Software Foundation; either version 3, or (at your option) any later
8+
// version.
9+
10+
// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
11+
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
12+
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13+
// for more details.
14+
15+
// You should have received a copy of the GNU General Public License
16+
// along with GCC; see the file COPYING3. If not see
17+
// <http://www.gnu.org/licenses/>.
18+
19+
#ifndef RUST_MACRO_BUILTINS_H
20+
#define RUST_MACRO_BUILTINS_H
21+
22+
#include "rust-ast.h"
23+
#include "rust-location.h"
24+
25+
namespace Rust {
26+
class MacroBuiltin
27+
{
28+
public:
29+
static AST::ASTFragment assert (Location invoc_locus,
30+
AST::MacroInvocData &invoc);
31+
};
32+
} // namespace Rust
33+
34+
#endif // RUST_MACRO_BUILTINS_H

gcc/rust/expand/rust-macro-expand.cc

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3194,8 +3194,14 @@ MacroExpander::expand_invoc (AST::MacroInvocation &invoc)
31943194
bool ok = mappings->lookup_macro_def (resolved_node, &rules_def);
31953195
rust_assert (ok);
31963196

3197-
auto fragment
3198-
= expand_decl_macro (invoc.get_locus (), invoc_data, *rules_def, false);
3197+
auto fragment = AST::ASTFragment::create_empty ();
3198+
3199+
if (rules_def->is_builtin ())
3200+
fragment
3201+
= rules_def->get_builtin_transcriber () (invoc.get_locus (), invoc_data);
3202+
else
3203+
fragment
3204+
= expand_decl_macro (invoc.get_locus (), invoc_data, *rules_def, false);
31993205

32003206
// lets attach this fragment to the invocation
32013207
invoc.set_fragment (std::move (fragment));
@@ -3229,8 +3235,14 @@ MacroExpander::expand_invoc_semi (AST::MacroInvocationSemi &invoc)
32293235
bool ok = mappings->lookup_macro_def (resolved_node, &rules_def);
32303236
rust_assert (ok);
32313237

3232-
auto fragment
3233-
= expand_decl_macro (invoc.get_locus (), invoc_data, *rules_def, true);
3238+
auto fragment = AST::ASTFragment::create_empty ();
3239+
3240+
if (rules_def->is_builtin ())
3241+
fragment
3242+
= rules_def->get_builtin_transcriber () (invoc.get_locus (), invoc_data);
3243+
else
3244+
fragment
3245+
= expand_decl_macro (invoc.get_locus (), invoc_data, *rules_def, true);
32343246

32353247
// lets attach this fragment to the invocation
32363248
invoc.set_fragment (std::move (fragment));

gcc/rust/util/rust-hir-map.cc

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#include "rust-hir-map.h"
2020
#include "rust-ast-full.h"
2121
#include "rust-hir-full.h"
22+
#include "rust-macro-builtins.h"
2223

2324
namespace Rust {
2425
namespace Analysis {
@@ -741,6 +742,16 @@ Mappings::iterate_trait_items (
741742
void
742743
Mappings::insert_macro_def (AST::MacroRulesDefinition *macro)
743744
{
745+
static std::map<std::string, std::function<AST::ASTFragment (
746+
Location, AST::MacroInvocData &)>>
747+
builtin_macros = {
748+
{"assert", MacroBuiltin::assert},
749+
};
750+
751+
auto builtin = builtin_macros.find (macro->get_rule_name ());
752+
if (builtin != builtin_macros.end ())
753+
macro->set_builtin_transcriber (builtin->second);
754+
744755
auto it = macroMappings.find (macro->get_node_id ());
745756
rust_assert (it == macroMappings.end ());
746757

0 commit comments

Comments
 (0)