// 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-compile-context.h" #include "rust-compile-type.h" namespace Rust { namespace Compile { Context::Context (::Backend *backend) : backend (backend), resolver (Resolver::Resolver::get ()), tyctx (Resolver::TypeCheckContext::get ()), mappings (Analysis::Mappings::get ()), mangler (Mangler ()) { setup_builtins (); } void Context::setup_builtins () { auto builtins = resolver->get_builtin_types (); for (auto it = builtins.begin (); it != builtins.end (); it++) { HirId ref; bool ok = tyctx->lookup_type_by_node_id ((*it)->get_node_id (), &ref); rust_assert (ok); TyTy::BaseType *lookup; ok = tyctx->lookup_type (ref, &lookup); rust_assert (ok); TyTyResolveCompile::compile (this, lookup); } } hashval_t Context::type_hasher (tree type) { inchash::hash hstate; hstate.add_int (TREE_CODE (type)); if (TYPE_NAME (type)) { hashval_t record_name_hash = IDENTIFIER_HASH_VALUE (DECL_NAME (TYPE_NAME (type))); hstate.add_object (record_name_hash); } for (tree t = TYPE_ATTRIBUTES (type); t; t = TREE_CHAIN (t)) /* Just the identifier is adequate to distinguish. */ hstate.add_object (IDENTIFIER_HASH_VALUE (TREE_PURPOSE (t))); switch (TREE_CODE (type)) { case METHOD_TYPE: hstate.add_object (TYPE_HASH (TYPE_METHOD_BASETYPE (type))); /* FALLTHROUGH. */ case FUNCTION_TYPE: for (tree t = TYPE_ARG_TYPES (type); t; t = TREE_CHAIN (t)) if (TREE_VALUE (t) != error_mark_node) hstate.add_object (TYPE_HASH (TREE_VALUE (t))); break; case OFFSET_TYPE: hstate.add_object (TYPE_HASH (TYPE_OFFSET_BASETYPE (type))); break; case ARRAY_TYPE: { if (TYPE_DOMAIN (type)) hstate.add_object (TYPE_HASH (TYPE_DOMAIN (type))); if (!AGGREGATE_TYPE_P (TREE_TYPE (type))) { unsigned typeless = TYPE_TYPELESS_STORAGE (type); hstate.add_object (typeless); } } break; case INTEGER_TYPE: { tree t = TYPE_MAX_VALUE (type); if (!t) t = TYPE_MIN_VALUE (type); for (int i = 0; i < TREE_INT_CST_NUNITS (t); i++) hstate.add_object (TREE_INT_CST_ELT (t, i)); break; } case REAL_TYPE: case FIXED_POINT_TYPE: { unsigned prec = TYPE_PRECISION (type); hstate.add_object (prec); break; } case VECTOR_TYPE: hstate.add_poly_int (TYPE_VECTOR_SUBPARTS (type)); break; case RECORD_TYPE: case UNION_TYPE: case QUAL_UNION_TYPE: { for (tree t = TYPE_FIELDS (type); t; t = TREE_CHAIN (t)) { hashval_t name_hash = IDENTIFIER_HASH_VALUE (DECL_NAME (t)); hashval_t type_hash = type_hasher (TREE_TYPE (t)); hstate.add_object (name_hash); hstate.add_object (type_hash); } } break; case BOOLEAN_TYPE: break; case REFERENCE_TYPE: case POINTER_TYPE: { hashval_t type_hash = type_hasher (TREE_TYPE (type)); hstate.add_object (type_hash); } break; default: break; } return hstate.end (); } void Context::push_closure_context (HirId id) { auto it = closure_bindings.find (id); rust_assert (it == closure_bindings.end ()); closure_bindings.insert ({id, {}}); closure_scope_bindings.push_back (id); } void Context::pop_closure_context () { rust_assert (!closure_scope_bindings.empty ()); HirId ref = closure_scope_bindings.back (); closure_scope_bindings.pop_back (); closure_bindings.erase (ref); } void Context::insert_closure_binding (HirId id, tree expr) { rust_assert (!closure_scope_bindings.empty ()); HirId ref = closure_scope_bindings.back (); closure_bindings[ref].insert ({id, expr}); } bool Context::lookup_closure_binding (HirId id, tree *expr) { if (closure_scope_bindings.empty ()) return false; HirId ref = closure_scope_bindings.back (); auto it = closure_bindings.find (ref); rust_assert (it != closure_bindings.end ()); auto iy = it->second.find (id); if (iy == it->second.end ()) return false; *expr = iy->second; return true; } } // namespace Compile } // namespace Rust