From patchwork Tue Dec 6 10:13:58 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Arthur Cohen X-Patchwork-Id: 61514 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 551B43837F44 for ; Tue, 6 Dec 2022 10:19:30 +0000 (GMT) X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from mail-wr1-x434.google.com (mail-wr1-x434.google.com [IPv6:2a00:1450:4864:20::434]) by sourceware.org (Postfix) with ESMTPS id 7505E395BC3B for ; Tue, 6 Dec 2022 10:12:28 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 7505E395BC3B Authentication-Results: sourceware.org; dmarc=none (p=none dis=none) header.from=embecosm.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=embecosm.com Received: by mail-wr1-x434.google.com with SMTP id h7so16733372wrs.6 for ; Tue, 06 Dec 2022 02:12:28 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=embecosm.com; s=google; h=content-transfer-encoding:mime-version:reply-to:references :in-reply-to:message-id:date:subject:cc:to:from:from:to:cc:subject :date:message-id:reply-to; bh=z/AUgFcH71LKS0WNcVuRnyBTrIkTErg4b32FcuIAT+M=; b=OdlBaTFLrCS0S0FYErl+ljZppZ/yQDAwZ8rOG0seYAPyGv4y29bUAnN5wrJNdijm5q Ee+XVub37sPTRP1HyCTmJRSVeU16XeEKVQOtOGs9CYztssk7QEus35061lOENaqJnsPw H3NDZVjO59Ejt0JhUX8Pczlcq7noYp0R5Wu7xUuFAydPVUXAEjcEdJzTH0LoxqZasEcE 2Eu1EMZa4AV7vefqxCEPRhsXqPkVFWkB+Bxqcg1gWNnE9b9eEG31VwJEVo2G7eFXJEw+ kP1scZbgBj5gqwhKFTPlGFn+SrJNhy+ehb7MzHr4EBSZygarsaveErytHLm4oVBmKDEH 21HA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=content-transfer-encoding:mime-version:reply-to:references :in-reply-to:message-id:date:subject:cc:to:from:x-gm-message-state :from:to:cc:subject:date:message-id:reply-to; bh=z/AUgFcH71LKS0WNcVuRnyBTrIkTErg4b32FcuIAT+M=; b=upqrI8BDBv/19F9nqIgAsPzCgWH9itzAN93HJiCWu2mxtCwlLH6s2wZY8/wt09tO/x LGvurUrzFI0KSKi7+nmwNnERwAWfoRnJY3UMbGMnZkFlNudO1dIH23oxHjdDeHyVfh8h tbrP5DSEMFfKe/amnM2XMGRx/50NYx1goEChYeodSf1kvcP4lOAq5BU88rbbJ6CogZcC 0CHSkFMJniGX4l3ptZ2yLNUdhj3Jk+mTNKdqnPcu21iKMigvnk59bzHpY7pEuRKAOHZz PgRfoqHydEPMeMKoED6g9LcJ5yZol6zKnDALX3L1EokmMCQcqcBxqFc4bc3FDC0ql3ER UBmQ== X-Gm-Message-State: ANoB5pmEctobXY35sBAPE89WDesdr1+cIYSmWCdWPyffJv6qg49jF6so jC1UpAaJnYWA4FTN/5myT4tF0izxJJm9waO9mQ== X-Google-Smtp-Source: AA0mqf5ehVjTIn6LqgHY5Dhly57KOQxs5haSb9DXW5Pq20Yo7AMg8P38aSfuAyOnwdYwuIPew5o3oA== X-Received: by 2002:adf:ea44:0:b0:242:19b2:f1fc with SMTP id j4-20020adfea44000000b0024219b2f1fcmr24353235wrn.593.1670321546227; Tue, 06 Dec 2022 02:12:26 -0800 (PST) Received: from platypus.lan ([2001:861:5e4c:3bb0:6424:328a:1734:3249]) by smtp.googlemail.com with ESMTPSA id r10-20020a05600c458a00b003cfd4a50d5asm27052699wmo.34.2022.12.06.02.12.25 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 06 Dec 2022 02:12:25 -0800 (PST) From: arthur.cohen@embecosm.com To: gcc-patches@gcc.gnu.org Cc: gcc-rust@gcc.gnu.org, Philip Herron Subject: [PATCH Rust front-end v4 26/46] gccrs: Add helpers mappings canonical path and lang items Date: Tue, 6 Dec 2022 11:13:58 +0100 Message-Id: <20221206101417.778807-27-arthur.cohen@embecosm.com> X-Mailer: git-send-email 2.38.1 In-Reply-To: <20221206101417.778807-1-arthur.cohen@embecosm.com> References: <20221206101417.778807-1-arthur.cohen@embecosm.com> MIME-Version: 1.0 X-Spam-Status: No, score=-19.1 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, KAM_SHORT, RCVD_IN_DNSWL_NONE, SPF_HELO_NONE, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org X-BeenThere: gcc-patches@gcc.gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gcc-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: arthur.cohen@embecosm.com Errors-To: gcc-patches-bounces+patchwork=sourceware.org@gcc.gnu.org Sender: "Gcc-patches" From: Philip Herron These are various helper classes used in the compiler pipeline. --- gcc/rust/util/rust-canonical-path.h | 195 +++++ gcc/rust/util/rust-common.h | 53 ++ gcc/rust/util/rust-hir-map.cc | 980 ++++++++++++++++++++++++++ gcc/rust/util/rust-hir-map.h | 356 ++++++++++ gcc/rust/util/rust-identifier.h | 49 ++ gcc/rust/util/rust-lang-item.h | 377 ++++++++++ gcc/rust/util/rust-mapping-common.h | 85 +++ gcc/rust/util/rust-stacked-contexts.h | 86 +++ 8 files changed, 2181 insertions(+) create mode 100644 gcc/rust/util/rust-canonical-path.h create mode 100644 gcc/rust/util/rust-common.h create mode 100644 gcc/rust/util/rust-hir-map.cc create mode 100644 gcc/rust/util/rust-hir-map.h create mode 100644 gcc/rust/util/rust-identifier.h create mode 100644 gcc/rust/util/rust-lang-item.h create mode 100644 gcc/rust/util/rust-mapping-common.h create mode 100644 gcc/rust/util/rust-stacked-contexts.h diff --git a/gcc/rust/util/rust-canonical-path.h b/gcc/rust/util/rust-canonical-path.h new file mode 100644 index 00000000000..54cc0390849 --- /dev/null +++ b/gcc/rust/util/rust-canonical-path.h @@ -0,0 +1,195 @@ +// 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 +// . + +#ifndef RUST_CANONICAL_PATH +#define RUST_CANONICAL_PATH + +#include "rust-system.h" +#include "rust-mapping-common.h" + +namespace Rust { +namespace Resolver { + +// https://doc.rust-lang.org/reference/paths.html#canonical-paths +// +// struct X - path X +// impl X { fn test - path X::test } +// +// struct X - path X +// +// impl X { fn test - path X::test} +// impl X { fn test - path X::test } +// impl X { fn test - path X::test } +// +// pub trait Trait { // ::a::Trait +// fn f(&self); // ::a::Trait::f +// } +// +// impl Trait for Struct { +// fn f(&self) {} // <::a::Struct as ::a::Trait>::f +// } +class CanonicalPath +{ +public: + CanonicalPath (const CanonicalPath &other) : segs (other.segs) {} + + CanonicalPath &operator= (const CanonicalPath &other) + { + segs = other.segs; + return *this; + } + + static CanonicalPath new_seg (NodeId id, const std::string &path) + { + rust_assert (!path.empty ()); + return CanonicalPath ({std::pair (id, path)}, + UNKNOWN_CREATENUM); + } + + static CanonicalPath + trait_impl_projection_seg (NodeId id, const CanonicalPath &trait_seg, + const CanonicalPath &impl_type_seg) + { + return CanonicalPath::new_seg (id, "<" + impl_type_seg.get () + " as " + + trait_seg.get () + ">"); + } + + std::string get () const + { + std::string buf; + for (size_t i = 0; i < segs.size (); i++) + { + bool have_more = (i + 1) < segs.size (); + const std::string &seg = segs.at (i).second; + buf += seg + (have_more ? "::" : ""); + } + return buf; + } + + static CanonicalPath get_big_self (NodeId id) + { + return CanonicalPath::new_seg (id, "Self"); + } + + static CanonicalPath create_empty () + { + return CanonicalPath ({}, UNKNOWN_CREATENUM); + } + + bool is_empty () const { return segs.size () == 0; } + + CanonicalPath append (const CanonicalPath &other) const + { + rust_assert (!other.is_empty ()); + if (is_empty ()) + return CanonicalPath (other.segs, crate_num); + + std::vector> copy (segs); + for (auto &s : other.segs) + copy.push_back (s); + + return CanonicalPath (copy, crate_num); + } + + // if we have the path A::B::C this will give a callback for each segment + // including the prefix, example: + // + // path: + // A::B::C + // + // iterate: + // A + // A::B + // A::B::C + void iterate (std::function cb) const + { + std::vector> buf; + for (auto &seg : segs) + { + buf.push_back (seg); + if (!cb (CanonicalPath (buf, crate_num))) + return; + } + } + + // if we have the path A::B::C this will give a callback for each segment + // example: + // + // path: + // A::B::C + // + // iterate: + // A + // B + // C + void iterate_segs (std::function cb) const + { + for (auto &seg : segs) + { + std::vector> buf; + buf.push_back ({seg.first, seg.second}); + if (!cb (CanonicalPath (buf, crate_num))) + return; + } + } + + size_t size () const { return segs.size (); } + + NodeId get_node_id () const + { + rust_assert (!segs.empty ()); + return segs.back ().first; + } + + const std::pair &get_seg_at (size_t index) const + { + rust_assert (index < size ()); + return segs.at (index); + } + + bool is_equal (const CanonicalPath &b) const + { + return get ().compare (b.get ()) == 0; + } + + void set_crate_num (CrateNum n) { crate_num = n; } + + CrateNum get_crate_num () const + { + rust_assert (crate_num != UNKNOWN_CREATENUM); + return crate_num; + } + + bool operator== (const CanonicalPath &b) const { return is_equal (b); } + + bool operator< (const CanonicalPath &b) const { return get () < b.get (); } + +private: + explicit CanonicalPath (std::vector> path, + CrateNum crate_num) + : segs (path), crate_num (crate_num) + {} + + std::vector> segs; + CrateNum crate_num; +}; + +} // namespace Resolver +} // namespace Rust + +#endif // RUST_CANONICAL_PATH diff --git a/gcc/rust/util/rust-common.h b/gcc/rust/util/rust-common.h new file mode 100644 index 00000000000..a3f6fb07d8d --- /dev/null +++ b/gcc/rust/util/rust-common.h @@ -0,0 +1,53 @@ +// Copyright (C) 2021-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 +// . + +// Common definitions useful throughout the Rust frontend. + +#ifndef RUST_COMMON +#define RUST_COMMON + +namespace Rust { + +enum Mutability +{ + Imm, + Mut +}; + +enum Unsafety +{ + Unsafe, + Normal +}; + +enum Polarity +{ + Positive, + Negative +}; + +enum AsyncConstStatus +{ + NONE, + CONST_FN, + ASYNC_FN +}; + +} // namespace Rust + +#endif // RUST_COMMON diff --git a/gcc/rust/util/rust-hir-map.cc b/gcc/rust/util/rust-hir-map.cc new file mode 100644 index 00000000000..8705fdcf381 --- /dev/null +++ b/gcc/rust/util/rust-hir-map.cc @@ -0,0 +1,980 @@ +// 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 +// . + +#include "rust-hir-map.h" +#include "rust-ast-full.h" +#include "rust-diagnostics.h" +#include "rust-hir-full.h" +#include "rust-macro-builtins.h" +#include "rust-mapping-common.h" + +namespace Rust { +namespace Analysis { + +NodeMapping +NodeMapping::get_error () +{ + return NodeMapping (UNKNOWN_CREATENUM, UNKNOWN_NODEID, UNKNOWN_HIRID, + UNKNOWN_LOCAL_DEFID); +} + +CrateNum +NodeMapping::get_crate_num () const +{ + return crateNum; +} + +NodeId +NodeMapping::get_nodeid () const +{ + return nodeId; +} + +HirId +NodeMapping::get_hirid () const +{ + return hirId; +} + +LocalDefId +NodeMapping::get_local_defid () const +{ + return localDefId; +} + +DefId +NodeMapping::get_defid () const +{ + return get_defid (get_crate_num (), get_local_defid ()); +} + +DefId +NodeMapping::get_defid (CrateNum crate_num, LocalDefId local_defid) +{ + return DefId{crate_num, local_defid}; +} + +std::string +NodeMapping::as_string () const +{ + std::ostringstream ss; + ss << "[" + << "C: " << get_crate_num (); + if (get_nodeid () != UNKNOWN_NODEID) + ss << " Nid: " << get_nodeid (); + + if (get_hirid () != UNKNOWN_HIRID) + ss << " Hid: " << get_hirid (); + + if (get_local_defid () != UNKNOWN_LOCAL_DEFID) + ss << " Lid: " << get_local_defid (); + + ss << "]"; + return ss.str (); +} + +// Mappings Class now +static const HirId kDefaultNodeIdBegin = 1; +static const HirId kDefaultHirIdBegin = 1; +static const HirId kDefaultCrateNumBegin = 0; + +Mappings::Mappings () + : crateNumItr (kDefaultCrateNumBegin), currentCrateNum (UNKNOWN_CREATENUM), + hirIdIter (kDefaultHirIdBegin), nodeIdIter (kDefaultNodeIdBegin) +{} + +Mappings::~Mappings () {} + +Mappings * +Mappings::get () +{ + static std::unique_ptr instance; + if (!instance) + instance = std::unique_ptr (new Mappings ()); + + return instance.get (); +} + +CrateNum +Mappings::get_next_crate_num (const std::string &name) +{ + auto id = crateNumItr; + crateNumItr++; + set_crate_name (id, name); + return id; +} + +void +Mappings::set_current_crate (CrateNum crateNum) +{ + currentCrateNum = crateNum; +} + +CrateNum +Mappings::get_current_crate () const +{ + return currentCrateNum; +} + +bool +Mappings::get_crate_name (CrateNum crate_num, std::string &name) const +{ + auto it = crate_names.find (crate_num); + if (it == crate_names.end ()) + return false; + + name.assign (it->second); + return true; +} + +void +Mappings::set_crate_name (CrateNum crate_num, const std::string &name) +{ + crate_names[crate_num] = name; +} + +std::string +Mappings::get_current_crate_name () const +{ + std::string name; + bool ok = get_crate_name (get_current_crate (), name); + rust_assert (ok); + return name; +} + +bool +Mappings::lookup_crate_name (const std::string &crate_name, + CrateNum &resolved_crate_num) const +{ + for (const auto &it : crate_names) + { + if (it.second.compare (crate_name) == 0) + { + resolved_crate_num = it.first; + return true; + } + } + return false; +} + +bool +Mappings::crate_num_to_nodeid (const CrateNum &crate_num, NodeId &node_id) const +{ + auto it = ast_crate_mappings.find (crate_num); + if (it == ast_crate_mappings.end ()) + return false; + + node_id = it->second->get_node_id (); + return true; +} + +bool +Mappings::node_is_crate (NodeId node_id) const +{ + for (const auto &it : ast_crate_mappings) + { + NodeId crate_node_id = it.second->get_node_id (); + if (crate_node_id == node_id) + return true; + } + return false; +} + +NodeId +Mappings::get_next_node_id () +{ + auto it = nodeIdIter; + nodeIdIter++; + return it; +} + +HirId +Mappings::get_next_hir_id (CrateNum crateNum) +{ + auto id = hirIdIter; + hirIdIter++; + + auto it = hirNodesWithinCrate.find (crateNum); + if (it == hirNodesWithinCrate.end ()) + { + hirNodesWithinCrate.insert ({crateNum, {}}); + } + + hirNodesWithinCrate[crateNum].insert (id); + return id; +} + +LocalDefId +Mappings::get_next_localdef_id (CrateNum crateNum) +{ + auto it = localIdIter.find (crateNum); + if (it == localIdIter.end ()) + { + localIdIter.insert ({crateNum, 1}); + } + + it = localIdIter.find (crateNum); + rust_assert (it != localIdIter.end ()); + + LocalDefId id = it->second; + localIdIter[crateNum] = id + 1; + return id; +} + +AST::Crate & +Mappings::get_ast_crate (CrateNum crateNum) +{ + auto it = ast_crate_mappings.find (crateNum); + rust_assert (it != ast_crate_mappings.end ()); + return *it->second; +} + +AST::Crate & +Mappings::get_ast_crate_by_node_id (NodeId id) +{ + auto i = crate_node_to_crate_num.find (id); + rust_assert (i != crate_node_to_crate_num.end ()); + + CrateNum crateNum = i->second; + auto it = ast_crate_mappings.find (crateNum); + rust_assert (it != ast_crate_mappings.end ()); + return *it->second; +} + +AST::Crate & +Mappings::insert_ast_crate (std::unique_ptr &&crate, + CrateNum crate_num) +{ + auto it = ast_crate_mappings.find (crate_num); + rust_assert (it == ast_crate_mappings.end ()); + + // store it + ast_crate_mappings.insert ({crate_num, crate.release ()}); + + // return the reference to it + it = ast_crate_mappings.find (crate_num); + rust_assert (it != ast_crate_mappings.end ()); + return *it->second; +} + +HIR::Crate & +Mappings::get_hir_crate (CrateNum crateNum) +{ + auto it = hir_crate_mappings.find (crateNum); + rust_assert (it != hir_crate_mappings.end ()); + return *it->second; +} + +bool +Mappings::is_local_hirid_crate (HirId crateNum) +{ + for (const auto &it : hir_crate_mappings) + { + const auto &crate = it.second; + if (crate->get_mappings ().get_hirid () == crateNum) + return true; + } + return false; +} + +HIR::Crate & +Mappings::insert_hir_crate (std::unique_ptr &&crate) +{ + CrateNum crateNum = crate->get_mappings ().get_crate_num (); + auto it = hir_crate_mappings.find (crateNum); + rust_assert (it == hir_crate_mappings.end ()); + + insert_node_to_hir (crate->get_mappings ().get_nodeid (), + crate->get_mappings ().get_hirid ()); + hir_crate_mappings.insert ({crateNum, crate.release ()}); + + it = hir_crate_mappings.find (crateNum); + rust_assert (it != hir_crate_mappings.end ()); + return *it->second; +} + +void +Mappings::insert_defid_mapping (DefId id, HIR::Item *item) +{ + CrateNum crate_num = id.crateNum; + LocalDefId local_def_id = id.localDefId; + + rust_assert (lookup_defid (id) == nullptr); + rust_assert (lookup_local_defid (crate_num, local_def_id) == nullptr); + + defIdMappings[id] = item; + insert_local_defid_mapping (crate_num, local_def_id, item); +} + +HIR::Item * +Mappings::lookup_defid (DefId id) +{ + auto it = defIdMappings.find (id); + if (it == defIdMappings.end ()) + return nullptr; + + return it->second; +} + +void +Mappings::insert_hir_item (HIR::Item *item) +{ + auto id = item->get_mappings ().get_hirid (); + rust_assert (lookup_hir_item (id) == nullptr); + + hirItemMappings[id] = item; + insert_node_to_hir (item->get_mappings ().get_nodeid (), id); +} + +HIR::Item * +Mappings::lookup_hir_item (HirId id) +{ + auto it = hirItemMappings.find (id); + if (it == hirItemMappings.end ()) + return nullptr; + + return it->second; +} + +void +Mappings::insert_hir_trait_item (HIR::TraitItem *item) +{ + auto id = item->get_mappings ().get_hirid (); + rust_assert (lookup_hir_trait_item (id) == nullptr); + + hirTraitItemMappings[id] = item; + insert_node_to_hir (item->get_mappings ().get_nodeid (), id); +} + +HIR::TraitItem * +Mappings::lookup_hir_trait_item (HirId id) +{ + auto it = hirTraitItemMappings.find (id); + if (it == hirTraitItemMappings.end ()) + return nullptr; + + return it->second; +} + +void +Mappings::insert_hir_extern_block (HIR::ExternBlock *block) +{ + auto id = block->get_mappings ().get_hirid (); + rust_assert (lookup_hir_extern_block (id) == nullptr); + + hirExternBlockMappings[id] = block; + insert_node_to_hir (block->get_mappings ().get_nodeid (), id); +} + +HIR::ExternBlock * +Mappings::lookup_hir_extern_block (HirId id) +{ + auto it = hirExternBlockMappings.find (id); + if (it == hirExternBlockMappings.end ()) + return nullptr; + + return it->second; +} + +void +Mappings::insert_hir_extern_item (HIR::ExternalItem *item, HirId parent_block) +{ + auto id = item->get_mappings ().get_hirid (); + rust_assert (lookup_hir_extern_item (id, nullptr) == nullptr); + + hirExternItemMappings[id] = {item, parent_block}; + insert_node_to_hir (item->get_mappings ().get_nodeid (), id); +} + +HIR::ExternalItem * +Mappings::lookup_hir_extern_item (HirId id, HirId *parent_block) +{ + auto it = hirExternItemMappings.find (id); + if (it == hirExternItemMappings.end ()) + return nullptr; + + *parent_block = it->second.second; + + return it->second.first; +} + +void +Mappings::insert_hir_impl_block (HIR::ImplBlock *item) +{ + auto id = item->get_mappings ().get_hirid (); + rust_assert (lookup_hir_impl_block (id) == nullptr); + + hirImplBlockMappings[id] = item; + insert_node_to_hir (item->get_mappings ().get_nodeid (), id); +} + +HIR::ImplBlock * +Mappings::lookup_hir_impl_block (HirId id) +{ + auto it = hirImplBlockMappings.find (id); + if (it == hirImplBlockMappings.end ()) + return nullptr; + + return it->second; +} + +void +Mappings::insert_module (HIR::Module *module) +{ + auto id = module->get_mappings ().get_hirid (); + rust_assert (lookup_module (id) == nullptr); + + hirModuleMappings[id] = module; + insert_node_to_hir (module->get_mappings ().get_nodeid (), id); +} + +HIR::Module * +Mappings::lookup_module (HirId id) +{ + auto it = hirModuleMappings.find (id); + if (it == hirModuleMappings.end ()) + return nullptr; + + return it->second; +} + +void +Mappings::insert_hir_implitem (HirId parent_impl_id, HIR::ImplItem *item) +{ + auto id = item->get_impl_mappings ().get_hirid (); + rust_assert (lookup_hir_implitem (id, nullptr) == nullptr); + + hirImplItemMappings[id] + = std::pair (parent_impl_id, item); + insert_node_to_hir (item->get_impl_mappings ().get_nodeid (), id); +} + +HIR::ImplItem * +Mappings::lookup_hir_implitem (HirId id, HirId *parent_impl_id) +{ + auto it = hirImplItemMappings.find (id); + if (it == hirImplItemMappings.end ()) + return nullptr; + + std::pair &ref = it->second; + if (parent_impl_id != nullptr) + *parent_impl_id = ref.first; + + return ref.second; +} + +void +Mappings::insert_hir_expr (HIR::Expr *expr) +{ + auto id = expr->get_mappings ().get_hirid (); + hirExprMappings[id] = expr; + + insert_node_to_hir (expr->get_mappings ().get_nodeid (), id); + insert_location (id, expr->get_locus ()); +} + +HIR::Expr * +Mappings::lookup_hir_expr (HirId id) +{ + auto it = hirExprMappings.find (id); + if (it == hirExprMappings.end ()) + return nullptr; + + return it->second; +} + +void +Mappings::insert_hir_path_expr_seg (HIR::PathExprSegment *expr) +{ + auto id = expr->get_mappings ().get_hirid (); + rust_assert (lookup_hir_path_expr_seg (id) == nullptr); + + hirPathSegMappings[id] = expr; + insert_node_to_hir (expr->get_mappings ().get_nodeid (), id); + insert_location (id, expr->get_locus ()); +} + +HIR::PathExprSegment * +Mappings::lookup_hir_path_expr_seg (HirId id) +{ + auto it = hirPathSegMappings.find (id); + if (it == hirPathSegMappings.end ()) + return nullptr; + + return it->second; +} + +void +Mappings::insert_hir_generic_param (HIR::GenericParam *param) +{ + auto id = param->get_mappings ().get_hirid (); + rust_assert (lookup_hir_generic_param (id) == nullptr); + + hirGenericParamMappings[id] = param; + insert_node_to_hir (param->get_mappings ().get_nodeid (), id); + insert_location (id, param->get_locus ()); +} + +HIR::GenericParam * +Mappings::lookup_hir_generic_param (HirId id) +{ + auto it = hirGenericParamMappings.find (id); + if (it == hirGenericParamMappings.end ()) + return nullptr; + + return it->second; +} + +void +Mappings::insert_hir_type (HIR::Type *type) +{ + auto id = type->get_mappings ().get_hirid (); + rust_assert (lookup_hir_type (id) == nullptr); + + hirTypeMappings[id] = type; + insert_node_to_hir (type->get_mappings ().get_nodeid (), id); +} + +HIR::Type * +Mappings::lookup_hir_type (HirId id) +{ + auto it = hirTypeMappings.find (id); + if (it == hirTypeMappings.end ()) + return nullptr; + + return it->second; +} + +void +Mappings::insert_hir_stmt (HIR::Stmt *stmt) +{ + auto id = stmt->get_mappings ().get_hirid (); + rust_assert (lookup_hir_stmt (id) == nullptr); + + hirStmtMappings[id] = stmt; + insert_node_to_hir (stmt->get_mappings ().get_nodeid (), id); +} + +HIR::Stmt * +Mappings::lookup_hir_stmt (HirId id) +{ + auto it = hirStmtMappings.find (id); + if (it == hirStmtMappings.end ()) + return nullptr; + + return it->second; +} + +void +Mappings::insert_hir_param (HIR::FunctionParam *param) +{ + auto id = param->get_mappings ().get_hirid (); + rust_assert (lookup_hir_param (id) == nullptr); + + hirParamMappings[id] = param; + insert_node_to_hir (param->get_mappings ().get_nodeid (), id); +} + +HIR::FunctionParam * +Mappings::lookup_hir_param (HirId id) +{ + auto it = hirParamMappings.find (id); + if (it == hirParamMappings.end ()) + return nullptr; + + return it->second; +} + +void +Mappings::insert_hir_self_param (HIR::SelfParam *param) +{ + auto id = param->get_mappings ().get_hirid (); + rust_assert (lookup_hir_self_param (id) == nullptr); + + hirSelfParamMappings[id] = param; + insert_node_to_hir (param->get_mappings ().get_nodeid (), id); +} + +HIR::SelfParam * +Mappings::lookup_hir_self_param (HirId id) +{ + auto it = hirSelfParamMappings.find (id); + if (it == hirSelfParamMappings.end ()) + return nullptr; + + return it->second; +} + +void +Mappings::insert_hir_struct_field (HIR::StructExprField *field) +{ + auto id = field->get_mappings ().get_hirid (); + rust_assert (lookup_hir_struct_field (id) == nullptr); + + hirStructFieldMappings[id] = field; + insert_node_to_hir (field->get_mappings ().get_nodeid (), id); +} + +HIR::StructExprField * +Mappings::lookup_hir_struct_field (HirId id) +{ + auto it = hirStructFieldMappings.find (id); + if (it == hirStructFieldMappings.end ()) + return nullptr; + + return it->second; +} + +void +Mappings::insert_hir_pattern (HIR::Pattern *pattern) +{ + auto id = pattern->get_pattern_mappings ().get_hirid (); + rust_assert (lookup_hir_pattern (id) == nullptr); + + hirPatternMappings[id] = pattern; + insert_node_to_hir (pattern->get_pattern_mappings ().get_nodeid (), id); +} + +HIR::Pattern * +Mappings::lookup_hir_pattern (HirId id) +{ + auto it = hirPatternMappings.find (id); + if (it == hirPatternMappings.end ()) + return nullptr; + + return it->second; +} + +void +Mappings::insert_local_defid_mapping (CrateNum crateNum, LocalDefId id, + HIR::Item *item) +{ + rust_assert (lookup_local_defid (crateNum, id) == nullptr); + localDefIdMappings[crateNum][id] = item; +} + +HIR::Item * +Mappings::lookup_local_defid (CrateNum crateNum, LocalDefId id) +{ + auto it = localDefIdMappings.find (crateNum); + if (it == localDefIdMappings.end ()) + return nullptr; + + auto iy = it->second.find (id); + if (iy == it->second.end ()) + return nullptr; + + return iy->second; +} + +void +Mappings::walk_local_defids_for_crate (CrateNum crateNum, + std::function cb) +{ + auto it = localDefIdMappings.find (crateNum); + if (it == localDefIdMappings.end ()) + return; + + for (auto iy = it->second.begin (); iy != it->second.end (); iy++) + { + if (!cb (iy->second)) + return; + } +} + +void +Mappings::insert_node_to_hir (NodeId id, HirId ref) +{ + nodeIdToHirMappings[id] = ref; + hirIdToNodeMappings[ref] = id; +} + +bool +Mappings::lookup_node_to_hir (NodeId id, HirId *ref) +{ + auto it = nodeIdToHirMappings.find (id); + if (it == nodeIdToHirMappings.end ()) + return false; + + *ref = it->second; + return true; +} + +bool +Mappings::lookup_hir_to_node (HirId id, NodeId *ref) +{ + auto it = hirIdToNodeMappings.find (id); + if (it == hirIdToNodeMappings.end ()) + return false; + + *ref = it->second; + return true; +} + +void +Mappings::insert_location (HirId id, Location locus) +{ + locations[id] = locus; +} + +Location +Mappings::lookup_location (HirId id) +{ + auto it = locations.find (id); + if (it == locations.end ()) + return Location (); + + return it->second; +} + +bool +Mappings::resolve_nodeid_to_stmt (NodeId id, HIR::Stmt **stmt) +{ + auto it = nodeIdToHirMappings.find (id); + if (it == nodeIdToHirMappings.end ()) + return false; + + HirId resolved = it->second; + auto resolved_stmt = lookup_hir_stmt (resolved); + *stmt = resolved_stmt; + return resolved_stmt != nullptr; +} + +void +Mappings::iterate_impl_items ( + std::function cb) +{ + for (auto it = hirImplItemMappings.begin (); it != hirImplItemMappings.end (); + it++) + { + auto id = it->first; + auto impl_item = it->second.second; + auto impl + = lookup_associated_impl (impl_item->get_impl_mappings ().get_hirid ()); + if (!cb (id, impl_item, impl)) + return; + } +} + +void +Mappings::iterate_impl_blocks (std::function cb) +{ + for (auto it = hirImplBlockMappings.begin (); + it != hirImplBlockMappings.end (); it++) + { + HirId id = it->first; + HIR::ImplBlock *impl_block = it->second; + if (!cb (id, impl_block)) + return; + } +} + +void +Mappings::iterate_trait_items ( + std::function cb) +{ + for (auto it = hirTraitItemMappings.begin (); + it != hirTraitItemMappings.end (); it++) + { + HirId trait_item_id = it->first; + HIR::TraitItem *trait_item = it->second; + HIR::Trait *trait = lookup_trait_item_mapping (trait_item_id); + + if (!cb (trait_item, trait)) + return; + } +} + +void +Mappings::insert_macro_def (AST::MacroRulesDefinition *macro) +{ + static std::map> + builtin_macros = { + {"assert", MacroBuiltin::assert}, + {"file", MacroBuiltin::file}, + {"line", MacroBuiltin::line}, + {"column", MacroBuiltin::column}, + {"include_bytes", MacroBuiltin::include_bytes}, + {"include_str", MacroBuiltin::include_str}, + {"compile_error", MacroBuiltin::compile_error}, + {"concat", MacroBuiltin::concat}, + {"env", MacroBuiltin::env}, + {"cfg", MacroBuiltin::cfg}, + {"include", MacroBuiltin::include}, + }; + + auto outer_attrs = macro->get_outer_attrs (); + bool should_be_builtin + = std::any_of (outer_attrs.begin (), outer_attrs.end (), + [] (AST::Attribute attr) { + return attr.get_path () == "rustc_builtin_macro"; + }); + if (should_be_builtin) + { + auto builtin = builtin_macros.find (macro->get_rule_name ()); + if (builtin != builtin_macros.end ()) + macro->set_builtin_transcriber (builtin->second); + else + rust_error_at (macro->get_locus (), + "cannot find a built-in macro with name %qs", + macro->get_rule_name ().c_str ()); + } + + auto it = macroMappings.find (macro->get_node_id ()); + rust_assert (it == macroMappings.end ()); + + macroMappings[macro->get_node_id ()] = macro; +} + +bool +Mappings::lookup_macro_def (NodeId id, AST::MacroRulesDefinition **def) +{ + auto it = macroMappings.find (id); + if (it == macroMappings.end ()) + return false; + + *def = it->second; + return true; +} + +void +Mappings::insert_visibility (NodeId id, Privacy::ModuleVisibility visibility) +{ + visibility_map.insert ({id, visibility}); +} + +bool +Mappings::lookup_visibility (NodeId id, Privacy::ModuleVisibility &def) +{ + auto it = visibility_map.find (id); + if (it == visibility_map.end ()) + return false; + + def = it->second; + return true; +} + +void +Mappings::insert_module_child (NodeId module, NodeId child) +{ + auto it = module_child_map.find (module); + if (it == module_child_map.end ()) + module_child_map.insert ({module, {child}}); + else + it->second.emplace_back (child); +} + +Optional &> +Mappings::lookup_module_children (NodeId module) +{ + auto it = module_child_map.find (module); + if (it == module_child_map.end ()) + return Optional &>::none (); + + return Optional &>::some (it->second); +} + +void +Mappings::insert_module_child_item (NodeId module, + Resolver::CanonicalPath child) +{ + rust_assert (!child.is_empty ()); + rust_assert (child.get_node_id () != UNKNOWN_NODEID); + + auto it = module_child_items.find (module); + if (it == module_child_items.end ()) + module_child_items.insert ({module, {child}}); + else + it->second.emplace_back (child); +} + +Optional &> +Mappings::lookup_module_chidren_items (NodeId module) +{ + auto it = module_child_items.find (module); + if (it == module_child_items.end ()) + return Optional &>::none (); + + return Optional &>::some (it->second); +} + +Optional +Mappings::lookup_module_child (NodeId module, const std::string &item_name) +{ + Optional &> children + = lookup_module_chidren_items (module); + if (children.is_none ()) + return Optional::none (); + + // lookup the children to match the name if we can + for (auto &child : children.get ()) + { + const std::string &raw_identifier = child.get (); + bool found = raw_identifier.compare (item_name) == 0; + if (found) + return Optional::some (child); + } + return Optional::none (); +} + +void +Mappings::insert_child_item_to_parent_module_mapping (NodeId child_item, + NodeId parent_module) +{ + child_to_parent_module_map.insert ({child_item, parent_module}); +} + +Optional +Mappings::lookup_parent_module (NodeId child_item) +{ + auto it = child_to_parent_module_map.find (child_item); + if (it == child_to_parent_module_map.end ()) + return Optional::none (); + + return Optional::some (it->second); +} + +bool +Mappings::node_is_module (NodeId query) +{ + return module_child_items.find (query) != module_child_items.end (); +} + +void +Mappings::insert_ast_item (AST::Item *item) +{ + auto it = ast_item_mappings.find (item->get_node_id ()); + rust_assert (it == ast_item_mappings.end ()); + + ast_item_mappings[item->get_node_id ()] = item; +} + +bool +Mappings::lookup_ast_item (NodeId id, AST::Item **result) +{ + auto it = ast_item_mappings.find (id); + if (it == ast_item_mappings.end ()) + return false; + + *result = it->second; + return true; +} + +} // namespace Analysis +} // namespace Rust diff --git a/gcc/rust/util/rust-hir-map.h b/gcc/rust/util/rust-hir-map.h new file mode 100644 index 00000000000..98fcfe6a6a7 --- /dev/null +++ b/gcc/rust/util/rust-hir-map.h @@ -0,0 +1,356 @@ +// 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 +// . + +#ifndef RUST_HIR_MAP_H +#define RUST_HIR_MAP_H + +#include "rust-optional.h" +#include "rust-system.h" +#include "rust-location.h" +#include "rust-mapping-common.h" +#include "rust-canonical-path.h" +#include "rust-ast-full-decls.h" +#include "rust-hir-full-decls.h" +#include "rust-lang-item.h" +#include "rust-privacy-common.h" + +namespace Rust { +namespace Analysis { + +class NodeMapping +{ +public: + NodeMapping (CrateNum crateNum, NodeId nodeId, HirId hirId, + LocalDefId localDefId) + : crateNum (crateNum), nodeId (nodeId), hirId (hirId), + localDefId (localDefId) + {} + + static NodeMapping get_error (); + + CrateNum get_crate_num () const; + NodeId get_nodeid () const; + HirId get_hirid () const; + LocalDefId get_local_defid () const; + DefId get_defid () const; + + static DefId get_defid (CrateNum crate_num, LocalDefId local_defid); + + std::string as_string () const; + + bool is_equal (const NodeMapping &other) const + { + return get_crate_num () == other.get_crate_num () + && get_nodeid () == other.get_nodeid () + && get_hirid () == other.get_hirid () + && get_local_defid () == other.get_local_defid (); + } + +private: + CrateNum crateNum; + NodeId nodeId; + HirId hirId; + LocalDefId localDefId; +}; + +class Mappings +{ +public: + static Mappings *get (); + ~Mappings (); + + CrateNum get_next_crate_num (const std::string &name); + void set_current_crate (CrateNum crateNum); + CrateNum get_current_crate () const; + bool get_crate_name (CrateNum crate_num, std::string &name) const; + void set_crate_name (CrateNum crate_num, const std::string &name); + std::string get_current_crate_name () const; + bool lookup_crate_name (const std::string &crate_name, + CrateNum &resolved_crate_num) const; + bool crate_num_to_nodeid (const CrateNum &crate_num, NodeId &node_id) const; + bool node_is_crate (NodeId node_id) const; + + NodeId get_next_node_id (); + HirId get_next_hir_id () { return get_next_hir_id (get_current_crate ()); } + HirId get_next_hir_id (CrateNum crateNum); + LocalDefId get_next_localdef_id () + { + return get_next_localdef_id (get_current_crate ()); + } + LocalDefId get_next_localdef_id (CrateNum crateNum); + + AST::Crate &get_ast_crate (CrateNum crateNum); + AST::Crate &get_ast_crate_by_node_id (NodeId id); + AST::Crate &insert_ast_crate (std::unique_ptr &&crate, + CrateNum crate_num); + HIR::Crate &insert_hir_crate (std::unique_ptr &&crate); + HIR::Crate &get_hir_crate (CrateNum crateNum); + bool is_local_hirid_crate (HirId crateNum); + + void insert_defid_mapping (DefId id, HIR::Item *item); + HIR::Item *lookup_defid (DefId id); + + void insert_local_defid_mapping (CrateNum crateNum, LocalDefId id, + HIR::Item *item); + HIR::Item *lookup_local_defid (CrateNum crateNum, LocalDefId id); + + void insert_hir_item (HIR::Item *item); + HIR::Item *lookup_hir_item (HirId id); + + void insert_hir_trait_item (HIR::TraitItem *item); + HIR::TraitItem *lookup_hir_trait_item (HirId id); + + void insert_hir_extern_block (HIR::ExternBlock *block); + HIR::ExternBlock *lookup_hir_extern_block (HirId id); + + void insert_hir_extern_item (HIR::ExternalItem *item, HirId parent_block); + HIR::ExternalItem *lookup_hir_extern_item (HirId id, HirId *parent_block); + + void insert_hir_impl_block (HIR::ImplBlock *item); + HIR::ImplBlock *lookup_hir_impl_block (HirId id); + + void insert_module (HIR::Module *module); + HIR::Module *lookup_module (HirId id); + + void insert_hir_implitem (HirId parent_impl_id, HIR::ImplItem *item); + HIR::ImplItem *lookup_hir_implitem (HirId id, HirId *parent_impl_id); + + void insert_hir_expr (HIR::Expr *expr); + HIR::Expr *lookup_hir_expr (HirId id); + + void insert_hir_path_expr_seg (HIR::PathExprSegment *expr); + HIR::PathExprSegment *lookup_hir_path_expr_seg (HirId id); + + void insert_hir_generic_param (HIR::GenericParam *expr); + HIR::GenericParam *lookup_hir_generic_param (HirId id); + + void insert_hir_type (HIR::Type *type); + HIR::Type *lookup_hir_type (HirId id); + + void insert_hir_stmt (HIR::Stmt *stmt); + HIR::Stmt *lookup_hir_stmt (HirId id); + + void insert_hir_param (HIR::FunctionParam *type); + HIR::FunctionParam *lookup_hir_param (HirId id); + + void insert_hir_self_param (HIR::SelfParam *type); + HIR::SelfParam *lookup_hir_self_param (HirId id); + + void insert_hir_struct_field (HIR::StructExprField *type); + HIR::StructExprField *lookup_hir_struct_field (HirId id); + + void insert_hir_pattern (HIR::Pattern *pattern); + HIR::Pattern *lookup_hir_pattern (HirId id); + + void walk_local_defids_for_crate (CrateNum crateNum, + std::function cb); + + void insert_node_to_hir (NodeId id, HirId ref); + bool lookup_node_to_hir (NodeId id, HirId *ref); + bool lookup_hir_to_node (HirId id, NodeId *ref); + + void insert_location (HirId id, Location locus); + Location lookup_location (HirId id); + + bool resolve_nodeid_to_stmt (NodeId id, HIR::Stmt **stmt); + + std::set &get_hirids_within_crate (CrateNum crate) + { + return hirNodesWithinCrate[crate]; + } + + void insert_impl_item_mapping (HirId impl_item_id, HIR::ImplBlock *impl) + { + rust_assert (hirImplItemsToImplMappings.find (impl_item_id) + == hirImplItemsToImplMappings.end ()); + hirImplItemsToImplMappings[impl_item_id] = impl; + } + + HIR::ImplBlock *lookup_associated_impl (HirId impl_item_id) + { + auto lookup = hirImplItemsToImplMappings.find (impl_item_id); + rust_assert (lookup != hirImplItemsToImplMappings.end ()); + return lookup->second; + } + + void iterate_impl_items ( + std::function cb); + + void iterate_impl_blocks (std::function cb); + + void iterate_trait_items ( + std::function cb); + + bool is_impl_item (HirId id) + { + HirId parent_impl_block_id = UNKNOWN_HIRID; + return lookup_hir_implitem (id, &parent_impl_block_id) != nullptr; + } + + void insert_trait_item_mapping (HirId trait_item_id, HIR::Trait *trait) + { + rust_assert (hirTraitItemsToTraitMappings.find (trait_item_id) + == hirTraitItemsToTraitMappings.end ()); + hirTraitItemsToTraitMappings[trait_item_id] = trait; + } + + HIR::Trait *lookup_trait_item_mapping (HirId trait_item_id) + { + auto lookup = hirTraitItemsToTraitMappings.find (trait_item_id); + rust_assert (lookup != hirTraitItemsToTraitMappings.end ()); + return lookup->second; + } + + void insert_canonical_path (NodeId id, const Resolver::CanonicalPath path) + { + const Resolver::CanonicalPath *p = nullptr; + if (lookup_canonical_path (id, &p)) + { + // if we have already stored a canonical path this is ok so long as + // this new path is equal or is smaller that the existing one but in + // that case we ignore it. + if (p->is_equal (path)) + return; + else + { + rust_assert (p->size () >= path.size ()); + return; + } + } + + paths.emplace (id, std::move (path)); + } + + bool lookup_canonical_path (NodeId id, const Resolver::CanonicalPath **path) + { + auto it = paths.find (id); + if (it == paths.end ()) + return false; + + *path = &it->second; + return true; + } + + void insert_lang_item (RustLangItem::ItemType item_type, DefId id) + { + auto it = lang_item_mappings.find (item_type); + rust_assert (it == lang_item_mappings.end ()); + + lang_item_mappings[item_type] = id; + } + + bool lookup_lang_item (RustLangItem::ItemType item_type, DefId *id) + { + auto it = lang_item_mappings.find (item_type); + if (it == lang_item_mappings.end ()) + return false; + + *id = it->second; + return true; + } + + void insert_macro_def (AST::MacroRulesDefinition *macro); + + bool lookup_macro_def (NodeId id, AST::MacroRulesDefinition **def); + + void insert_visibility (NodeId id, Privacy::ModuleVisibility visibility); + bool lookup_visibility (NodeId id, Privacy::ModuleVisibility &def); + + void insert_module_child (NodeId module, NodeId child); + Optional &> lookup_module_children (NodeId module); + + void insert_module_child_item (NodeId module, Resolver::CanonicalPath item); + Optional &> + lookup_module_chidren_items (NodeId module); + Optional + lookup_module_child (NodeId module, const std::string &item_name); + + void insert_child_item_to_parent_module_mapping (NodeId child_item, + NodeId parent_module); + Optional lookup_parent_module (NodeId child_item); + bool node_is_module (NodeId query); + + void insert_ast_item (AST::Item *item); + bool lookup_ast_item (NodeId id, AST::Item **result); + +private: + Mappings (); + + CrateNum crateNumItr; + CrateNum currentCrateNum; + HirId hirIdIter; + NodeId nodeIdIter; + std::map localIdIter; + + std::map crate_node_to_crate_num; + std::map ast_crate_mappings; + std::map hir_crate_mappings; + std::map defIdMappings; + std::map> localDefIdMappings; + + std::map hirModuleMappings; + std::map hirItemMappings; + std::map hirTypeMappings; + std::map hirExprMappings; + std::map hirStmtMappings; + std::map hirParamMappings; + std::map hirStructFieldMappings; + std::map> hirImplItemMappings; + std::map hirSelfParamMappings; + std::map hirImplItemsToImplMappings; + std::map hirImplBlockMappings; + std::map hirTraitItemMappings; + std::map hirExternBlockMappings; + std::map> hirExternItemMappings; + std::map hirPathSegMappings; + std::map hirGenericParamMappings; + std::map hirTraitItemsToTraitMappings; + std::map hirPatternMappings; + std::map lang_item_mappings; + std::map paths; + std::map locations; + std::map nodeIdToHirMappings; + std::map hirIdToNodeMappings; + + // all hirid nodes + std::map> hirNodesWithinCrate; + + // macros + std::map macroMappings; + + // crate names + std::map crate_names; + + // Low level visibility map for each DefId + std::map visibility_map; + + // Module tree maps + + // Maps each module's node id to a list of its children + std::map> module_child_map; + std::map> module_child_items; + std::map child_to_parent_module_map; + + // AST mappings + std::map ast_item_mappings; +}; + +} // namespace Analysis +} // namespace Rust + +#endif // RUST_HIR_MAP_H diff --git a/gcc/rust/util/rust-identifier.h b/gcc/rust/util/rust-identifier.h new file mode 100644 index 00000000000..0b5cb70b373 --- /dev/null +++ b/gcc/rust/util/rust-identifier.h @@ -0,0 +1,49 @@ +// 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 +// . + +#ifndef RUST_IDENTIFIER +#define RUST_IDENTIFIER + +#include "rust-canonical-path.h" +#include "rust-location.h" + +namespace Rust { + +struct RustIdent +{ + Resolver::CanonicalPath path; + Location locus; + + RustIdent (const Resolver::CanonicalPath &path, Location locus) + : path (path), locus (locus) + {} + + RustIdent (const RustIdent &other) : path (other.path), locus (other.locus) {} + + RustIdent &operator= (const RustIdent &other) + { + path = other.path; + locus = other.locus; + + return *this; + } +}; + +} // namespace Rust + +#endif // RUST_IDENTIFIER diff --git a/gcc/rust/util/rust-lang-item.h b/gcc/rust/util/rust-lang-item.h new file mode 100644 index 00000000000..9d1ee900aec --- /dev/null +++ b/gcc/rust/util/rust-lang-item.h @@ -0,0 +1,377 @@ +// 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 +// . + +#include "rust-system.h" +#include "operator.h" + +namespace Rust { +namespace Analysis { + +// https://github.com/rust-lang/rust/blob/master/library/core/src/ops/arith.rs +class RustLangItem +{ +public: + enum ItemType + { + ADD, + SUBTRACT, + MULTIPLY, + DIVIDE, + REMAINDER, + BITAND, + BITOR, + BITXOR, + SHL, + SHR, + + NEGATION, + NOT, + + ADD_ASSIGN, + SUB_ASSIGN, + MUL_ASSIGN, + DIV_ASSIGN, + REM_ASSIGN, + BITAND_ASSIGN, + BITOR_ASSIGN, + BITXOR_ASSIGN, + SHL_ASSIGN, + SHR_ASSIGN, + + DEREF, + DEREF_MUT, + + // https://github.com/rust-lang/rust/blob/master/library/core/src/ops/index.rs + INDEX, + INDEX_MUT, + + // https://github.com/rust-lang/rust/blob/master/library/core/src/ops/range.rs + RANGE_FULL, + RANGE, + RANGE_FROM, + RANGE_TO, + RANGE_INCLUSIVE, + RANGE_TO_INCLUSIVE, + + // https://github.com/rust-lang/rust/blob/master/library/core/src/ptr/const_ptr.rs + CONST_PTR, + MUT_PTR, + CONST_SLICE_PTR, + + UNKNOWN, + }; + + static ItemType Parse (const std::string &item) + { + if (item.compare ("add") == 0) + { + return ItemType::ADD; + } + else if (item.compare ("sub") == 0) + { + return ItemType::SUBTRACT; + } + else if (item.compare ("mul") == 0) + { + return ItemType::MULTIPLY; + } + else if (item.compare ("div") == 0) + { + return ItemType::DIVIDE; + } + else if (item.compare ("rem") == 0) + { + return ItemType::REMAINDER; + } + else if (item.compare ("bitand") == 0) + { + return ItemType::BITAND; + } + else if (item.compare ("bitor") == 0) + { + return ItemType::BITOR; + } + else if (item.compare ("bitxor") == 0) + { + return ItemType::BITXOR; + } + else if (item.compare ("shl") == 0) + { + return ItemType::SHL; + } + else if (item.compare ("shr") == 0) + { + return ItemType::SHR; + } + else if (item.compare ("neg") == 0) + { + return ItemType::NEGATION; + } + else if (item.compare ("not") == 0) + { + return ItemType::NOT; + } + else if (item.compare ("add_assign") == 0) + { + return ItemType::ADD_ASSIGN; + } + else if (item.compare ("sub_assign") == 0) + { + return ItemType::SUB_ASSIGN; + } + else if (item.compare ("mul_assign") == 0) + { + return ItemType::MUL_ASSIGN; + } + else if (item.compare ("div_assign") == 0) + { + return ItemType::DIV_ASSIGN; + } + else if (item.compare ("rem_assign") == 0) + { + return ItemType::REM_ASSIGN; + } + else if (item.compare ("bitand_assign") == 0) + { + return ItemType::BITAND_ASSIGN; + } + else if (item.compare ("bitor_assign") == 0) + { + return ItemType::BITOR_ASSIGN; + } + else if (item.compare ("bitxor_assign") == 0) + { + return ItemType::BITXOR_ASSIGN; + } + else if (item.compare ("shl_assign") == 0) + { + return ItemType::SHL_ASSIGN; + } + else if (item.compare ("shr_assign") == 0) + { + return ItemType::SHR_ASSIGN; + } + else if (item.compare ("deref") == 0) + { + return ItemType::DEREF; + } + else if (item.compare ("deref_mut") == 0) + { + return ItemType::DEREF_MUT; + } + else if (item.compare ("index") == 0) + { + return ItemType::INDEX; + } + else if (item.compare ("index_mut") == 0) + { + return ItemType::INDEX_MUT; + } + else if (item.compare ("RangeFull") == 0) + { + return ItemType::RANGE_FULL; + } + else if (item.compare ("Range") == 0) + { + return ItemType::RANGE; + } + else if (item.compare ("RangeFrom") == 0) + { + return ItemType::RANGE_FROM; + } + else if (item.compare ("RangeTo") == 0) + { + return ItemType::RANGE_TO; + } + else if (item.compare ("RangeInclusive") == 0) + { + return ItemType::RANGE_INCLUSIVE; + } + else if (item.compare ("RangeToInclusive") == 0) + { + return ItemType::RANGE_TO_INCLUSIVE; + } + else if (item.compare ("const_ptr") == 0) + { + return ItemType::CONST_PTR; + } + else if (item.compare ("mut_ptr") == 0) + { + return ItemType::MUT_PTR; + } + else if (item.compare ("const_slice_ptr") == 0) + { + return ItemType::CONST_SLICE_PTR; + } + + return ItemType::UNKNOWN; + } + + static std::string ToString (ItemType type) + { + switch (type) + { + case ADD: + return "add"; + case SUBTRACT: + return "sub"; + case MULTIPLY: + return "mul"; + case DIVIDE: + return "div"; + case REMAINDER: + return "rem"; + case BITAND: + return "bitand"; + case BITOR: + return "bitor"; + case BITXOR: + return "bitxor"; + case SHL: + return "shl"; + case SHR: + return "shr"; + case NEGATION: + return "neg"; + case NOT: + return "not"; + case ADD_ASSIGN: + return "add_assign"; + case SUB_ASSIGN: + return "sub_assign"; + case MUL_ASSIGN: + return "mul_assign"; + case DIV_ASSIGN: + return "div_assign"; + case REM_ASSIGN: + return "rem_assign"; + case BITAND_ASSIGN: + return "bitand_assign"; + case BITOR_ASSIGN: + return "bitor_assign"; + case BITXOR_ASSIGN: + return "bitxor_assign"; + case SHL_ASSIGN: + return "shl_assign"; + case SHR_ASSIGN: + return "shr_assign"; + case DEREF: + return "deref"; + case DEREF_MUT: + return "deref_mut"; + case INDEX: + return "index"; + case INDEX_MUT: + return "index_mut"; + case RANGE_FULL: + return "RangeFull"; + case RANGE: + return "Range"; + case RANGE_FROM: + return "RangeFrom"; + case RANGE_TO: + return "RangeTo"; + case RANGE_INCLUSIVE: + return "RangeInclusive"; + case RANGE_TO_INCLUSIVE: + return "RangeToInclusive"; + case CONST_PTR: + return "const_ptr"; + case MUT_PTR: + return "mut_ptr"; + case CONST_SLICE_PTR: + return "const_slice_ptr"; + + case UNKNOWN: + return ""; + } + return ""; + } + + static ItemType OperatorToLangItem (ArithmeticOrLogicalOperator op) + { + switch (op) + { + case ArithmeticOrLogicalOperator::ADD: + return ItemType::ADD; + case ArithmeticOrLogicalOperator::SUBTRACT: + return ItemType::SUBTRACT; + case ArithmeticOrLogicalOperator::MULTIPLY: + return ItemType::MULTIPLY; + case ArithmeticOrLogicalOperator::DIVIDE: + return ItemType::DIVIDE; + case ArithmeticOrLogicalOperator::MODULUS: + return ItemType::REMAINDER; + case ArithmeticOrLogicalOperator::BITWISE_AND: + return ItemType::BITAND; + case ArithmeticOrLogicalOperator::BITWISE_OR: + return ItemType::BITOR; + case ArithmeticOrLogicalOperator::BITWISE_XOR: + return ItemType::BITXOR; + case ArithmeticOrLogicalOperator::LEFT_SHIFT: + return ItemType::SHL; + case ArithmeticOrLogicalOperator::RIGHT_SHIFT: + return ItemType::SHR; + } + return ItemType::UNKNOWN; + } + + static ItemType + CompoundAssignmentOperatorToLangItem (ArithmeticOrLogicalOperator op) + { + switch (op) + { + case ArithmeticOrLogicalOperator::ADD: + return ItemType::ADD_ASSIGN; + case ArithmeticOrLogicalOperator::SUBTRACT: + return ItemType::SUB_ASSIGN; + case ArithmeticOrLogicalOperator::MULTIPLY: + return ItemType::MUL_ASSIGN; + case ArithmeticOrLogicalOperator::DIVIDE: + return ItemType::DIV_ASSIGN; + case ArithmeticOrLogicalOperator::MODULUS: + return ItemType::REM_ASSIGN; + case ArithmeticOrLogicalOperator::BITWISE_AND: + return ItemType::BITAND_ASSIGN; + case ArithmeticOrLogicalOperator::BITWISE_OR: + return ItemType::BITOR_ASSIGN; + case ArithmeticOrLogicalOperator::BITWISE_XOR: + return ItemType::BITXOR_ASSIGN; + case ArithmeticOrLogicalOperator::LEFT_SHIFT: + return ItemType::SHL_ASSIGN; + case ArithmeticOrLogicalOperator::RIGHT_SHIFT: + return ItemType::SHR_ASSIGN; + } + return ItemType::UNKNOWN; + } + + static ItemType NegationOperatorToLangItem (NegationOperator op) + { + switch (op) + { + case NegationOperator::NEGATE: + return ItemType::NEGATION; + case NegationOperator::NOT: + return ItemType::NOT; + } + return ItemType::UNKNOWN; + } +}; + +} // namespace Analysis +} // namespace Rust diff --git a/gcc/rust/util/rust-mapping-common.h b/gcc/rust/util/rust-mapping-common.h new file mode 100644 index 00000000000..c440ae98931 --- /dev/null +++ b/gcc/rust/util/rust-mapping-common.h @@ -0,0 +1,85 @@ +// 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 +// . + +#ifndef RUST_MAPPING_COMMON +#define RUST_MAPPING_COMMON + +#include "rust-system.h" + +namespace Rust { + +// refers to a Crate +typedef uint32_t CrateNum; +// refers to any node in the AST in current Crate +typedef uint32_t NodeId; +// refers to any node in the HIR for the current crate +typedef uint32_t HirId; +// refers to any top-level decl in HIR +typedef uint32_t LocalDefId; + +struct DefId +{ + CrateNum crateNum; + LocalDefId localDefId; + + bool operator== (const DefId &other) const + { + return this->crateNum == other.crateNum + && this->localDefId == other.localDefId; + } + + bool operator!= (const DefId &other) const { return !(*this == other); } + + bool operator< (const DefId &other) const + { + return ((uint64_t) this->crateNum << 32 | this->localDefId) + < ((uint64_t) other.crateNum << 32 | other.localDefId); + } + + std::string as_string () const + { + std::string buf; + buf += std::to_string (crateNum); + buf += " "; // or anything else + buf += std::to_string (localDefId); + return buf; + } +}; + +#define UNKNOWN_CREATENUM ((uint32_t) (0)) +#define UNKNOWN_NODEID ((uint32_t) (0)) +#define UNKNOWN_HIRID ((uint32_t) (0)) +#define UNKNOWN_LOCAL_DEFID ((uint32_t) (0)) +#define UNKNOWN_DEFID (DefId{0, 0}) + +} // namespace Rust + +namespace std { +template <> struct hash +{ + size_t operator() (const Rust::DefId &id) const noexcept + { + // TODO: Check if we can improve performance by having a better hash + // algorithm for `DefId`s + return hash () (hash () (id.crateNum) + + hash () (id.localDefId)); + } +}; +} // namespace std + +#endif // RUST_MAPPING_COMMON diff --git a/gcc/rust/util/rust-stacked-contexts.h b/gcc/rust/util/rust-stacked-contexts.h new file mode 100644 index 00000000000..c34eb907f06 --- /dev/null +++ b/gcc/rust/util/rust-stacked-contexts.h @@ -0,0 +1,86 @@ +// 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 +// . + +#ifndef RUST_CONTEXT_STACK_H +#define RUST_CONTEXT_STACK_H + +#include "rust-system.h" + +namespace Rust { + +/** + * Context stack util class. This class is useful for situations where you can + * enter the same kind of context multiple times. For example, when dealing with + * unsafe contexts, you might be tempted to simply keep a boolean value. + * + * ```rust + * let a = 15; + * unsafe { // we set the boolean to true + * // Now unsafe operations are allowed! + * let b = *(&a as *const i32); + * let c = std::mem::transmute(b); // Urgh! + * } // we set it to false + * ``` + * + * However, since the language allows nested unsafe blocks, you may run into + * this situation: + * + * ```rust + * unsafe { // we set the boolean to true + * unsafe { // we set the boolean to true + * } // we set it to false + * + * // Now unsafe operations are forbidden again, the boolean is false + * let f = std::mem::transmute(15); // Error! + * } // we set it to false + * ``` + */ +template class StackedContexts +{ +public: + /** + * Enter a special context + */ + void enter (T value) { stack.emplace_back (value); } + + /** + * Exit a special context + */ + T exit () + { + rust_assert (!stack.empty ()); + + auto last = stack.back (); + stack.pop_back (); + + return last; + } + + /** + * Are we currently inside of a special context? + */ + bool is_in_context () const { return !stack.empty (); } + +private: + /* Actual data */ + std::vector stack; +}; + +} // namespace Rust + +#endif /* !RUST_CONTEXT_STACK_H */