aboutsummaryrefslogtreecommitdiff
path: root/gcc/rust/resolve/rust-name-resolver.cc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/rust/resolve/rust-name-resolver.cc')
-rw-r--r--gcc/rust/resolve/rust-name-resolver.cc503
1 files changed, 503 insertions, 0 deletions
diff --git a/gcc/rust/resolve/rust-name-resolver.cc b/gcc/rust/resolve/rust-name-resolver.cc
new file mode 100644
index 0000000..fb70874
--- /dev/null
+++ b/gcc/rust/resolve/rust-name-resolver.cc
@@ -0,0 +1,503 @@
+// 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-name-resolver.h"
+#include "rust-ast-full.h"
+
+#define MKBUILTIN_TYPE(_X, _R, _TY) \
+ do \
+ { \
+ AST::PathIdentSegment seg (_X, Linemap::predeclared_location ()); \
+ auto typePath = ::std::unique_ptr<AST::TypePathSegment> ( \
+ new AST::TypePathSegment (::std::move (seg), false, \
+ Linemap::predeclared_location ())); \
+ ::std::vector< ::std::unique_ptr<AST::TypePathSegment> > segs; \
+ segs.push_back (::std::move (typePath)); \
+ auto builtin_type \
+ = new AST::TypePath (::std::move (segs), \
+ Linemap::predeclared_location (), false); \
+ _R.push_back (builtin_type); \
+ tyctx->insert_builtin (_TY->get_ref (), builtin_type->get_node_id (), \
+ _TY); \
+ mappings->insert_node_to_hir (builtin_type->get_node_id (), \
+ _TY->get_ref ()); \
+ mappings->insert_canonical_path ( \
+ builtin_type->get_node_id (), \
+ CanonicalPath::new_seg (builtin_type->get_node_id (), _X)); \
+ } \
+ while (0)
+
+namespace Rust {
+namespace Resolver {
+
+Rib::Rib (CrateNum crateNum, NodeId node_id)
+ : crate_num (crateNum), node_id (node_id),
+ mappings (Analysis::Mappings::get ())
+{}
+
+void
+Rib::insert_name (
+ const CanonicalPath &path, NodeId id, Location locus, bool shadow,
+ std::function<void (const CanonicalPath &, NodeId, Location)> dup_cb)
+{
+ auto it = path_mappings.find (path);
+ bool path_already_exists = it != path_mappings.end ();
+ if (path_already_exists && !shadow)
+ {
+ const auto &decl = decls_within_rib.find (it->second);
+ if (decl != decls_within_rib.end ())
+ dup_cb (path, it->second, decl->second);
+ else
+ dup_cb (path, it->second, locus);
+
+ return;
+ }
+
+ path_mappings[path] = id;
+ reverse_path_mappings.insert (std::pair<NodeId, CanonicalPath> (id, path));
+ decls_within_rib.insert (std::pair<NodeId, Location> (id, locus));
+ references[id] = {};
+}
+
+bool
+Rib::lookup_name (const CanonicalPath &ident, NodeId *id)
+{
+ auto it = path_mappings.find (ident);
+ if (it == path_mappings.end ())
+ return false;
+
+ *id = it->second;
+ return true;
+}
+
+void
+Rib::clear_name (const CanonicalPath &ident, NodeId id)
+{
+ auto ii = path_mappings.find (ident);
+ if (ii != path_mappings.end ())
+ path_mappings.erase (ii);
+
+ auto ij = reverse_path_mappings.find (id);
+ if (ij != reverse_path_mappings.end ())
+ reverse_path_mappings.erase (ij);
+
+ auto ik = decls_within_rib.find (id);
+ if (ik != decls_within_rib.end ())
+ decls_within_rib.erase (ik);
+}
+
+void
+Rib::append_reference_for_def (NodeId def, NodeId ref)
+{
+ references[def].insert (ref);
+}
+
+bool
+Rib::have_references_for_node (NodeId def) const
+{
+ auto it = references.find (def);
+ if (it == references.end ())
+ return false;
+
+ return !it->second.empty ();
+}
+
+bool
+Rib::decl_was_declared_here (NodeId def) const
+{
+ for (auto &it : decls_within_rib)
+ {
+ if (it.first == def)
+ return true;
+ }
+ return false;
+}
+
+void
+Rib::debug () const
+{
+ fprintf (stderr, "%s\n", debug_str ().c_str ());
+}
+
+std::string
+Rib::debug_str () const
+{
+ std::string buffer;
+ for (const auto &it : path_mappings)
+ {
+ buffer += it.first.get () + "=" + std::to_string (it.second);
+ buffer += ",";
+ }
+ return "{" + buffer + "}";
+}
+
+Scope::Scope (CrateNum crate_num) : crate_num (crate_num) {}
+
+void
+Scope::insert (
+ const CanonicalPath &ident, NodeId id, Location locus, bool shadow,
+ std::function<void (const CanonicalPath &, NodeId, Location)> dup_cb)
+{
+ peek ()->insert_name (ident, id, locus, shadow, dup_cb);
+}
+
+void
+Scope::insert (const CanonicalPath &ident, NodeId id, Location locus)
+{
+ peek ()->insert_name (ident, id, locus, true,
+ [] (const CanonicalPath &, NodeId, Location) -> void {
+ });
+}
+
+bool
+Scope::lookup (const CanonicalPath &ident, NodeId *id)
+{
+ NodeId lookup = UNKNOWN_NODEID;
+ iterate ([&] (Rib *r) mutable -> bool {
+ if (r->lookup_name (ident, &lookup))
+ return false;
+ return true;
+ });
+
+ *id = lookup;
+ return lookup != UNKNOWN_NODEID;
+}
+
+void
+Scope::iterate (std::function<bool (Rib *)> cb)
+{
+ for (auto it = stack.rbegin (); it != stack.rend (); ++it)
+ {
+ if (!cb (*it))
+ return;
+ }
+}
+
+void
+Scope::iterate (std::function<bool (const Rib *)> cb) const
+{
+ for (auto it = stack.rbegin (); it != stack.rend (); ++it)
+ {
+ if (!cb (*it))
+ return;
+ }
+}
+
+Rib *
+Scope::peek ()
+{
+ return stack.back ();
+}
+
+void
+Scope::push (NodeId id)
+{
+ stack.push_back (new Rib (get_crate_num (), id));
+}
+
+Rib *
+Scope::pop ()
+{
+ Rib *r = peek ();
+ stack.pop_back ();
+ return r;
+}
+
+void
+Scope::append_reference_for_def (NodeId refId, NodeId defId)
+{
+ bool ok = false;
+ iterate ([&] (Rib *r) mutable -> bool {
+ if (r->decl_was_declared_here (defId))
+ {
+ ok = true;
+ r->append_reference_for_def (defId, refId);
+ }
+ return true;
+ });
+ rust_assert (ok);
+}
+
+bool
+Scope::decl_was_declared_here (NodeId def) const
+{
+ bool found = false;
+ iterate ([&] (const Rib *r) -> bool {
+ if (r->decl_was_declared_here (def))
+ {
+ found = true;
+ return false;
+ }
+ return true;
+ });
+ return found;
+}
+
+Resolver::Resolver ()
+ : mappings (Analysis::Mappings::get ()), tyctx (TypeCheckContext::get ()),
+ name_scope (Scope (mappings->get_current_crate ())),
+ type_scope (Scope (mappings->get_current_crate ())),
+ label_scope (Scope (mappings->get_current_crate ())),
+ macro_scope (Scope (mappings->get_current_crate ())),
+ global_type_node_id (UNKNOWN_NODEID), unit_ty_node_id (UNKNOWN_NODEID)
+{
+ generate_builtins ();
+}
+
+Resolver *
+Resolver::get ()
+{
+ static Resolver *instance;
+ if (instance == nullptr)
+ instance = new Resolver ();
+
+ return instance;
+}
+
+void
+Resolver::push_new_name_rib (Rib *r)
+{
+ rust_assert (name_ribs.find (r->get_node_id ()) == name_ribs.end ());
+ name_ribs[r->get_node_id ()] = r;
+}
+
+void
+Resolver::push_new_type_rib (Rib *r)
+{
+ if (type_ribs.size () == 0)
+ global_type_node_id = r->get_node_id ();
+
+ rust_assert (type_ribs.find (r->get_node_id ()) == type_ribs.end ());
+ type_ribs[r->get_node_id ()] = r;
+}
+
+void
+Resolver::push_new_label_rib (Rib *r)
+{
+ rust_assert (label_ribs.find (r->get_node_id ()) == label_ribs.end ());
+ label_ribs[r->get_node_id ()] = r;
+}
+
+void
+Resolver::push_new_macro_rib (Rib *r)
+{
+ rust_assert (label_ribs.find (r->get_node_id ()) == label_ribs.end ());
+ macro_ribs[r->get_node_id ()] = r;
+}
+
+bool
+Resolver::find_name_rib (NodeId id, Rib **rib)
+{
+ auto it = name_ribs.find (id);
+ if (it == name_ribs.end ())
+ return false;
+
+ *rib = it->second;
+ return true;
+}
+
+bool
+Resolver::find_type_rib (NodeId id, Rib **rib)
+{
+ auto it = type_ribs.find (id);
+ if (it == type_ribs.end ())
+ return false;
+
+ *rib = it->second;
+ return true;
+}
+
+bool
+Resolver::find_macro_rib (NodeId id, Rib **rib)
+{
+ auto it = macro_ribs.find (id);
+ if (it == macro_ribs.end ())
+ return false;
+
+ *rib = it->second;
+ return true;
+}
+
+void
+Resolver::insert_builtin_types (Rib *r)
+{
+ auto builtins = get_builtin_types ();
+ for (auto &builtin : builtins)
+ {
+ CanonicalPath builtin_path
+ = CanonicalPath::new_seg (builtin->get_node_id (),
+ builtin->as_string ());
+ r->insert_name (builtin_path, builtin->get_node_id (),
+ Linemap::predeclared_location (), false,
+ [] (const CanonicalPath &, NodeId, Location) -> void {});
+ }
+}
+
+std::vector<AST::Type *> &
+Resolver::get_builtin_types ()
+{
+ return builtins;
+}
+
+void
+Resolver::generate_builtins ()
+{
+ auto u8
+ = new TyTy::UintType (mappings->get_next_hir_id (), TyTy::UintType::U8);
+ auto u16
+ = new TyTy::UintType (mappings->get_next_hir_id (), TyTy::UintType::U16);
+ auto u32
+ = new TyTy::UintType (mappings->get_next_hir_id (), TyTy::UintType::U32);
+ auto u64
+ = new TyTy::UintType (mappings->get_next_hir_id (), TyTy::UintType::U64);
+ auto u128
+ = new TyTy::UintType (mappings->get_next_hir_id (), TyTy::UintType::U128);
+ auto i8 = new TyTy::IntType (mappings->get_next_hir_id (), TyTy::IntType::I8);
+ auto i16
+ = new TyTy::IntType (mappings->get_next_hir_id (), TyTy::IntType::I16);
+ auto i32
+ = new TyTy::IntType (mappings->get_next_hir_id (), TyTy::IntType::I32);
+ auto i64
+ = new TyTy::IntType (mappings->get_next_hir_id (), TyTy::IntType::I64);
+ auto i128
+ = new TyTy::IntType (mappings->get_next_hir_id (), TyTy::IntType::I128);
+ auto rbool = new TyTy::BoolType (mappings->get_next_hir_id ());
+ auto f32
+ = new TyTy::FloatType (mappings->get_next_hir_id (), TyTy::FloatType::F32);
+ auto f64
+ = new TyTy::FloatType (mappings->get_next_hir_id (), TyTy::FloatType::F64);
+ auto usize = new TyTy::USizeType (mappings->get_next_hir_id ());
+ auto isize = new TyTy::ISizeType (mappings->get_next_hir_id ());
+ auto char_tyty = new TyTy::CharType (mappings->get_next_hir_id ());
+ auto str = new TyTy::StrType (mappings->get_next_hir_id ());
+ auto never = new TyTy::NeverType (mappings->get_next_hir_id ());
+
+ MKBUILTIN_TYPE ("u8", builtins, u8);
+ MKBUILTIN_TYPE ("u16", builtins, u16);
+ MKBUILTIN_TYPE ("u32", builtins, u32);
+ MKBUILTIN_TYPE ("u64", builtins, u64);
+ MKBUILTIN_TYPE ("u128", builtins, u128);
+ MKBUILTIN_TYPE ("i8", builtins, i8);
+ MKBUILTIN_TYPE ("i16", builtins, i16);
+ MKBUILTIN_TYPE ("i32", builtins, i32);
+ MKBUILTIN_TYPE ("i64", builtins, i64);
+ MKBUILTIN_TYPE ("i128", builtins, i128);
+ MKBUILTIN_TYPE ("bool", builtins, rbool);
+ MKBUILTIN_TYPE ("f32", builtins, f32);
+ MKBUILTIN_TYPE ("f64", builtins, f64);
+ MKBUILTIN_TYPE ("usize", builtins, usize);
+ MKBUILTIN_TYPE ("isize", builtins, isize);
+ MKBUILTIN_TYPE ("char", builtins, char_tyty);
+ MKBUILTIN_TYPE ("str", builtins, str);
+ MKBUILTIN_TYPE ("!", builtins, never);
+
+ // unit type ()
+ TyTy::TupleType *unit_tyty
+ = TyTy::TupleType::get_unit_type (mappings->get_next_hir_id ());
+ std::vector<std::unique_ptr<AST::Type> > elems;
+ AST::TupleType *unit_type
+ = new AST::TupleType (std::move (elems), Linemap::predeclared_location ());
+ builtins.push_back (unit_type);
+ tyctx->insert_builtin (unit_tyty->get_ref (), unit_type->get_node_id (),
+ unit_tyty);
+ set_unit_type_node_id (unit_type->get_node_id ());
+}
+
+void
+Resolver::insert_resolved_name (NodeId refId, NodeId defId)
+{
+ resolved_names[refId] = defId;
+ get_name_scope ().append_reference_for_def (refId, defId);
+}
+
+bool
+Resolver::lookup_resolved_name (NodeId refId, NodeId *defId)
+{
+ auto it = resolved_names.find (refId);
+ if (it == resolved_names.end ())
+ return false;
+
+ *defId = it->second;
+ return true;
+}
+
+void
+Resolver::insert_resolved_type (NodeId refId, NodeId defId)
+{
+ // auto it = resolved_types.find (refId);
+ // rust_assert (it == resolved_types.end ());
+
+ resolved_types[refId] = defId;
+ get_type_scope ().append_reference_for_def (refId, defId);
+}
+
+bool
+Resolver::lookup_resolved_type (NodeId refId, NodeId *defId)
+{
+ auto it = resolved_types.find (refId);
+ if (it == resolved_types.end ())
+ return false;
+
+ *defId = it->second;
+ return true;
+}
+
+void
+Resolver::insert_resolved_label (NodeId refId, NodeId defId)
+{
+ auto it = resolved_labels.find (refId);
+ rust_assert (it == resolved_labels.end ());
+
+ resolved_labels[refId] = defId;
+ get_label_scope ().append_reference_for_def (refId, defId);
+}
+
+bool
+Resolver::lookup_resolved_label (NodeId refId, NodeId *defId)
+{
+ auto it = resolved_labels.find (refId);
+ if (it == resolved_labels.end ())
+ return false;
+
+ *defId = it->second;
+ return true;
+}
+
+void
+Resolver::insert_resolved_macro (NodeId refId, NodeId defId)
+{
+ auto it = resolved_macros.find (refId);
+ rust_assert (it == resolved_macros.end ());
+
+ resolved_labels[refId] = defId;
+ get_label_scope ().append_reference_for_def (refId, defId);
+}
+
+bool
+Resolver::lookup_resolved_macro (NodeId refId, NodeId *defId)
+{
+ auto it = resolved_macros.find (refId);
+ if (it == resolved_macros.end ())
+ return false;
+
+ *defId = it->second;
+ return true;
+}
+
+} // namespace Resolver
+} // namespace Rust