// Copyright (C) 2020-2023 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 // . #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 ( \ new AST::TypePathSegment (::std::move (seg), false, \ Linemap::predeclared_location ())); \ ::std::vector< ::std::unique_ptr > 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 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 (id, path)); decls_within_rib.insert (std::pair (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 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 cb) { for (auto it = stack.rbegin (); it != stack.rend (); ++it) { if (!cb (*it)) return; } } void Scope::iterate (std::function 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 & 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 > 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