Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Collect lang items during AST #3274

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion gcc/rust/Make-lang.in
Original file line number Diff line number Diff line change
Expand Up @@ -227,8 +227,9 @@ GRS_OBJS = \
rust/rust-dir-owner.o \
rust/rust-unicode.o \
rust/rust-punycode.o \
rust/rust-lang-item.o \
rust/rust-expand-format-args.o \
rust/rust-lang-item.o \
rust/rust-collect-lang-items.o \
$(END)
# removed object files from here

Expand Down
96 changes: 96 additions & 0 deletions gcc/rust/ast/rust-collect-lang-items.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
// 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/>.

#include "rust-collect-lang-items.h"
#include "optional.h"
#include "rust-ast-collector.h"
#include "rust-ast.h"
#include "rust-attribute-values.h"
#include "rust-attributes.h"
#include "rust-hir-map.h"

namespace Rust {
namespace AST {

// FIXME: Before merging: De-duplicate with function in rust-ast-lower-base.cc
bool
is_known_attribute (const std::string &attribute_path)
{
const auto &lookup
= Analysis::BuiltinAttributeMappings::get ()->lookup_builtin (
attribute_path);

return !lookup.is_error ();
}

template <typename T>
tl::optional<LangItem::Kind>
get_lang_item_attr (const T &maybe_lang_item)
{
for (const auto &attr : maybe_lang_item.get_outer_attrs ())
{
const auto &str_path = attr.get_path ().as_string ();
if (!is_known_attribute (str_path))
{
rust_error_at (attr.get_locus (), "unknown attribute");
continue;
}

bool is_lang_item = str_path == Values::Attributes::LANG
&& attr.has_attr_input ()
&& attr.get_attr_input ().get_attr_input_type ()
== AST::AttrInput::AttrInputType::LITERAL;

if (is_lang_item)
{
auto &literal = static_cast<AST::AttrInputLiteral &> (attr.get_attr_input ());
const auto &lang_item_type_str = literal.get_literal ().as_string ();

return LangItem::Parse (lang_item_type_str);
}
}

return tl::nullopt;
}

template <typename T>
void
CollectLangItems::maybe_add_lang_item (const T &item)
{
if (auto lang_item = get_lang_item_attr (item))
mappings.insert_lang_item_node (lang_item.value (), item.get_node_id ());
}

void
CollectLangItems::visit (AST::Trait &item)
{
maybe_add_lang_item (item);

DefaultASTVisitor::visit(item);
}

void
CollectLangItems::visit (AST::TraitItemType &item)
{
maybe_add_lang_item (item);

DefaultASTVisitor::visit(item);
}

} // namespace AST
} // namespace Rust
58 changes: 58 additions & 0 deletions gcc/rust/ast/rust-collect-lang-items.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
// 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_COLLECT_LANG_ITEMS_H
#define RUST_COLLECT_LANG_ITEMS_H

#include "rust-ast-visitor.h"
#include "rust-ast.h"
#include "rust-hir-map.h"
#include "rust-item.h"

namespace Rust {
namespace AST {

// This class collects lang items ahead of lowering, as they are now needed for
// some parts of name resolution
class CollectLangItems : public DefaultASTVisitor
{
public:
CollectLangItems () : mappings (Analysis::Mappings::get ()){};

void go (AST::Crate &crate) { DefaultASTVisitor::visit (crate); }

Analysis::Mappings &mappings;

// We must implement visitors for all constructs that could be lang items.
// Lang items can be traits, but also enums, and even enum variants.
//
// https://github.com/rust-lang/rust/blob/master/compiler/rustc_hir/src/lang_items.rs

using DefaultASTVisitor::visit;

void visit (AST::Trait &item) override;
void visit (AST::TraitItemType &item) override;

private:
template <typename T> void maybe_add_lang_item (const T &item);
};

} // namespace AST
} // namespace Rust

#endif // ! RUST_COLLECT_LANG_ITEMS_H
3 changes: 3 additions & 0 deletions gcc/rust/rust-session-manager.cc
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
// <http://www.gnu.org/licenses/>.

#include "rust-session-manager.h"
#include "rust-collect-lang-items.h"
#include "rust-diagnostics.h"
#include "rust-hir-pattern-analysis.h"
#include "rust-immutable-name-resolution-context.h"
Expand Down Expand Up @@ -600,6 +601,8 @@ Session::compile_crate (const char *filename)
if (last_step == CompileOptions::CompileStep::Expansion)
return;

AST::CollectLangItems ().go (parsed_crate);

auto name_resolution_ctx = Resolver2_0::NameResolutionContext ();
// expansion pipeline stage

Expand Down
22 changes: 22 additions & 0 deletions gcc/rust/util/rust-hir-map.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1241,6 +1241,9 @@ Mappings::lookup_builtin_marker ()
return builtinMarker;
}

// FIXME: Before merging: Should we remove the `locus` parameter here? since
// lang items are looked up mostly for code generation, it doesn't make sense to
// error out on the locus of the node trying to access an inexistant lang item
DefId
Mappings::get_lang_item (LangItem::Kind item_type, location_t locus)
{
Expand Down Expand Up @@ -1277,5 +1280,24 @@ Mappings::lookup_lang_item (LangItem::Kind item_type)
return it->second;
}

void
Mappings::insert_lang_item_node (LangItem::Kind item_type, NodeId node_id)
{
auto it = lang_item_nodes.find (item_type);
rust_assert (it == lang_item_nodes.end ());

lang_item_nodes.insert ({item_type, node_id});
}

tl::optional<NodeId &>
Mappings::lookup_lang_item_node (LangItem::Kind item_type)
{
auto it = lang_item_nodes.find (item_type);
if (it == lang_item_nodes.end ())
return tl::nullopt;

return it->second;
}

} // namespace Analysis
} // namespace Rust
8 changes: 8 additions & 0 deletions gcc/rust/util/rust-hir-map.h
Original file line number Diff line number Diff line change
Expand Up @@ -259,6 +259,9 @@ class Mappings
void insert_lang_item (LangItem::Kind item_type, DefId id);
tl::optional<DefId &> lookup_lang_item (LangItem::Kind item_type);

void insert_lang_item_node (LangItem::Kind item_type, NodeId node_id);
tl::optional<NodeId &> lookup_lang_item_node (LangItem::Kind item_type);

// This will fatal_error when this lang item does not exist
DefId get_lang_item (LangItem::Kind item_type, location_t locus);

Expand Down Expand Up @@ -375,7 +378,12 @@ class Mappings
std::map<HirId, HIR::GenericParam *> hirGenericParamMappings;
std::map<HirId, HIR::Trait *> hirTraitItemsToTraitMappings;
std::map<HirId, HIR::Pattern *> hirPatternMappings;

// We need to have two maps here, as lang-items need to be used for both AST
// passes and HIR passes. Thus those two maps are created at different times.
std::map<LangItem::Kind, DefId> lang_item_mappings;
std::map<LangItem::Kind, NodeId> lang_item_nodes;

std::map<NodeId, Resolver::CanonicalPath> paths;
std::map<NodeId, location_t> locations;
std::map<NodeId, HirId> nodeIdToHirMappings;
Expand Down
Loading