blob: 018897e39b2dd098b8afd18b89a6aab576b00e22 [file] [log] [blame]
// 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
// <http://www.gnu.org/licenses/>.
#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