// Copyright (C) 2020-2021 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-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 "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, 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; } 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 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; } }; 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 (); void set_current_crate (CrateNum crateNum); CrateNum get_current_crate () const; CrateNum setup_crate_mappings (std::string crate_name); bool 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; } std::string get_current_crate_name () const { std::string name; bool ok = get_crate_name (get_current_crate (), name); rust_assert (ok); return name; } NodeId get_next_node_id () { return get_next_node_id (get_current_crate ()); } NodeId get_next_node_id (CrateNum crateNum); 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 (CrateNum crateNum); AST::Crate *get_ast_crate (CrateNum crateNum); void insert_ast_crate (AST::Crate *crate); HIR::Crate *get_hir_crate (CrateNum crateNum); void insert_hir_crate (HIR::Crate *crate); 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 (CrateNum crateNum, HirId id, HIR::Item *item); HIR::Item *lookup_hir_item (CrateNum crateNum, HirId id); void insert_hir_trait_item (CrateNum crateNum, HirId id, HIR::TraitItem *item); HIR::TraitItem *lookup_hir_trait_item (CrateNum crateNum, HirId id); void insert_hir_extern_item (CrateNum crateNum, HirId id, HIR::ExternalItem *item); HIR::ExternalItem *lookup_hir_extern_item (CrateNum crateNum, HirId id); void insert_hir_impl_block (CrateNum crateNum, HirId id, HIR::ImplBlock *item); HIR::ImplBlock *lookup_hir_impl_block (CrateNum crateNum, HirId id); void insert_module (CrateNum crateNum, HirId id, HIR::Module *module); HIR::Module *lookup_module (CrateNum crateNum, HirId id); void insert_hir_implitem (CrateNum crateNum, HirId id, HirId parent_impl_id, HIR::ImplItem *item); HIR::ImplItem *lookup_hir_implitem (CrateNum crateNum, HirId id, HirId *parent_impl_id); void insert_hir_expr (CrateNum crateNum, HirId id, HIR::Expr *expr); HIR::Expr *lookup_hir_expr (CrateNum crateNum, HirId id); void insert_hir_path_expr_seg (CrateNum crateNum, HirId id, HIR::PathExprSegment *expr); HIR::PathExprSegment *lookup_hir_path_expr_seg (CrateNum crateNum, HirId id); void insert_hir_generic_param (CrateNum crateNum, HirId id, HIR::GenericParam *expr); HIR::GenericParam *lookup_hir_generic_param (CrateNum crateNum, HirId id); void insert_hir_type (CrateNum crateNum, HirId id, HIR::Type *type); HIR::Type *lookup_hir_type (CrateNum crateNum, HirId id); void insert_hir_stmt (CrateNum crateNum, HirId id, HIR::Stmt *type); HIR::Stmt *lookup_hir_stmt (CrateNum crateNum, HirId id); void insert_hir_param (CrateNum crateNum, HirId id, HIR::FunctionParam *type); HIR::FunctionParam *lookup_hir_param (CrateNum crateNum, HirId id); void insert_hir_self_param (CrateNum crateNum, HirId id, HIR::SelfParam *type); HIR::SelfParam *lookup_hir_self_param (CrateNum crateNum, HirId id); void insert_hir_struct_field (CrateNum crateNum, HirId id, HIR::StructExprField *type); HIR::StructExprField *lookup_hir_struct_field (CrateNum crateNum, HirId id); void insert_hir_pattern (CrateNum crateNum, HirId id, HIR::Pattern *pattern); HIR::Pattern *lookup_hir_pattern (CrateNum crateNum, HirId id); void walk_local_defids_for_crate (CrateNum crateNum, std::function cb); void insert_node_to_hir (CrateNum crate, NodeId id, HirId ref); bool lookup_node_to_hir (CrateNum crate, NodeId id, HirId *ref); void insert_location (CrateNum crate, HirId id, Location locus); Location lookup_location (CrateNum crate, HirId id); Location lookup_location (HirId id) { return lookup_location (get_current_crate (), id); } bool resolve_nodeid_to_stmt (CrateNum crate, NodeId id, HIR::Stmt **stmt); bool resolve_nodeid_to_stmt (NodeId id, HIR::Stmt **stmt) { return resolve_nodeid_to_stmt (get_current_crate (), id, 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 (get_current_crate (), 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 (CrateNum crate, NodeId id, const Resolver::CanonicalPath path) { const Resolver::CanonicalPath *p = nullptr; if (lookup_canonical_path (crate, 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[crate].emplace (id, std::move (path)); } bool lookup_canonical_path (CrateNum crate, NodeId id, const Resolver::CanonicalPath **path) { auto it = paths.find (crate); if (it == paths.end ()) return false; auto iy = it->second.find (id); if (iy == it->second.end ()) return false; *path = &iy->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; } private: Mappings (); CrateNum crateNumItr = 0; CrateNum currentCrateNum; std::map hirIdIter; std::map nodeIdIter; std::map localIdIter; std::map astCrateMappings; std::map hirCrateMappings; 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> hirExternItemMappings; std::map> hirPathSegMappings; std::map> hirGenericParamMappings; std::map hirTraitItemsToTraitMappings; std::map> hirPatternMappings; // this maps the lang= to DefId mappings std::map lang_item_mappings; // canonical paths std::map> paths; // location info std::map> locations; // reverse mappings std::map> nodeIdToHirMappings; // all hirid nodes std::map> hirNodesWithinCrate; // crate names std::map crate_names; }; } // namespace Analysis } // namespace Rust #endif // RUST_HIR_MAP_H