// Copyright (C) 2020-2025 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.h"
#include "rust-compile-item.h"
#include "rust-compile-implitem.h"
#include "rust-hir-type-bounds.h"
#include "rust-compile-type.h"
#include "rust-substitution-mapper.h"
#include "rust-type-util.h"
#include "rust-session-manager.h"

namespace Rust {
namespace Compile {

CompileCrate::CompileCrate (HIR::Crate &crate, Context *ctx)
  : crate (crate), ctx (ctx)
{}

CompileCrate::~CompileCrate () {}

void
CompileCrate::Compile (HIR::Crate &crate, Context *ctx)
{
  CompileCrate c (crate, ctx);
  c.go ();
}

void
CompileCrate::go ()
{
  for (auto &item : crate.get_items ())
    CompileItem::compile (item.get (), ctx);
  auto crate_type
    = Rust::Session::get_instance ().options.target_data.get_crate_type ();
  if (crate_type == TargetOptions::CrateType::PROC_MACRO)
    add_proc_macro_symbols ();
}

// Shared methods in compilation

tree
HIRCompileBase::coercion_site (HirId id, tree rvalue, TyTy::BaseType *rval,
			       TyTy::BaseType *lval, location_t lvalue_locus,
			       location_t rvalue_locus)
{
  std::vector<Resolver::Adjustment> *adjustments = nullptr;
  bool ok = ctx->get_tyctx ()->lookup_autoderef_mappings (id, &adjustments);
  if (ok)
    {
      rvalue = resolve_adjustements (*adjustments, rvalue, rvalue_locus);
    }

  return coercion_site1 (rvalue, rval, lval, lvalue_locus, rvalue_locus);
}

tree
HIRCompileBase::coercion_site1 (tree rvalue, TyTy::BaseType *rval,
				TyTy::BaseType *lval, location_t lvalue_locus,
				location_t rvalue_locus)
{
  if (rvalue == error_mark_node)
    return error_mark_node;

  TyTy::BaseType *actual = rval->destructure ();
  TyTy::BaseType *expected = lval->destructure ();

  if (expected->get_kind () == TyTy::TypeKind::REF)
    {
      // this is a dyn object
      if (RS_DST_FLAG_P (TREE_TYPE (rvalue)))
	{
	  return rvalue;
	}

      // bad coercion... of something to a reference
      if (actual->get_kind () != TyTy::TypeKind::REF)
	return error_mark_node;

      const TyTy::ReferenceType *exp
	= static_cast<const TyTy::ReferenceType *> (expected);
      const TyTy::ReferenceType *act
	= static_cast<const TyTy::ReferenceType *> (actual);

      tree deref_rvalue = indirect_expression (rvalue, rvalue_locus);
      tree coerced
	= coercion_site1 (deref_rvalue, act->get_base (), exp->get_base (),
			  lvalue_locus, rvalue_locus);
      if (exp->is_dyn_object () && RS_DST_FLAG_P (TREE_TYPE (coerced)))
	return coerced;

      return address_expression (coerced, rvalue_locus);
    }
  else if (expected->get_kind () == TyTy::TypeKind::POINTER)
    {
      // this is a dyn object
      if (RS_DST_FLAG_P (TREE_TYPE (rvalue)))
	{
	  return rvalue;
	}

      // bad coercion... of something to a reference
      bool valid_coercion = actual->get_kind () == TyTy::TypeKind::REF
			    || actual->get_kind () == TyTy::TypeKind::POINTER;
      if (!valid_coercion)
	return error_mark_node;

      const TyTy::PointerType *exp
	= static_cast<const TyTy::PointerType *> (expected);

      TyTy::BaseType *actual_base = nullptr;
      if (actual->get_kind () == TyTy::TypeKind::REF)
	{
	  const TyTy::ReferenceType *act
	    = static_cast<const TyTy::ReferenceType *> (actual);

	  actual_base = act->get_base ();
	}
      else if (actual->get_kind () == TyTy::TypeKind::POINTER)
	{
	  const TyTy::PointerType *act
	    = static_cast<const TyTy::PointerType *> (actual);

	  actual_base = act->get_base ();
	}
      rust_assert (actual_base != nullptr);

      tree deref_rvalue = indirect_expression (rvalue, rvalue_locus);
      tree coerced
	= coercion_site1 (deref_rvalue, actual_base, exp->get_base (),
			  lvalue_locus, rvalue_locus);

      if (exp->is_dyn_object () && RS_DST_FLAG_P (TREE_TYPE (coerced)))
	return coerced;

      return address_expression (coerced, rvalue_locus);
    }
  else if (expected->get_kind () == TyTy::TypeKind::ARRAY)
    {
      if (actual->get_kind () != TyTy::TypeKind::ARRAY)
	return error_mark_node;

      tree tree_rval_type = TyTyResolveCompile::compile (ctx, actual);
      tree tree_lval_type = TyTyResolveCompile::compile (ctx, expected);
      if (!verify_array_capacities (tree_lval_type, tree_rval_type,
				    lvalue_locus, rvalue_locus))
	return error_mark_node;
    }
  else if (expected->get_kind () == TyTy::TypeKind::SLICE)
    {
      // bad coercion
      bool valid_coercion = actual->get_kind () == TyTy::TypeKind::SLICE
			    || actual->get_kind () == TyTy::TypeKind::ARRAY;
      if (!valid_coercion)
	return error_mark_node;

      // nothing to do here
      if (actual->get_kind () == TyTy::TypeKind::SLICE)
	return rvalue;

      // return an unsized coercion
      Resolver::Adjustment unsize_adj (
	Resolver::Adjustment::AdjustmentType::UNSIZE, actual, expected);
      return resolve_unsized_adjustment (unsize_adj, rvalue, rvalue_locus);
    }

  return rvalue;
}

tree
HIRCompileBase::coerce_to_dyn_object (tree compiled_ref,
				      const TyTy::BaseType *actual,
				      const TyTy::DynamicObjectType *ty,
				      location_t locus)
{
  // DST's get wrapped in a pseudo reference that doesnt exist...
  const TyTy::ReferenceType r (ctx->get_mappings ().get_next_hir_id (),
			       TyTy::TyVar (ty->get_ref ()), Mutability::Imm);

  tree dynamic_object = TyTyResolveCompile::compile (ctx, &r);
  tree dynamic_object_fields = TYPE_FIELDS (dynamic_object);
  tree vtable_field = DECL_CHAIN (dynamic_object_fields);
  rust_assert (TREE_CODE (TREE_TYPE (vtable_field)) == ARRAY_TYPE);

  //' this assumes ordering and current the structure is
  // __trait_object_ptr
  // [list of function ptrs]

  std::vector<std::pair<Resolver::TraitReference *, HIR::ImplBlock *>>
    probed_bounds_for_receiver = Resolver::TypeBoundsProbe::Probe (actual);

  tree address_of_compiled_ref = null_pointer_node;
  if (!actual->is_unit ())
    address_of_compiled_ref = address_expression (compiled_ref, locus);

  std::vector<tree> vtable_ctor_elems;
  std::vector<unsigned long> vtable_ctor_idx;
  unsigned long i = 0;
  for (auto &bound : ty->get_object_items ())
    {
      const Resolver::TraitItemReference *item = bound.first;
      const TyTy::TypeBoundPredicate *predicate = bound.second;

      auto address = compute_address_for_trait_item (item, predicate,
						     probed_bounds_for_receiver,
						     actual, actual, locus);
      vtable_ctor_elems.push_back (address);
      vtable_ctor_idx.push_back (i++);
    }

  tree vtable_ctor
    = Backend::array_constructor_expression (TREE_TYPE (vtable_field),
					     vtable_ctor_idx, vtable_ctor_elems,
					     locus);

  std::vector<tree> dyn_ctor = {address_of_compiled_ref, vtable_ctor};
  return Backend::constructor_expression (dynamic_object, false, dyn_ctor, -1,
					  locus);
}

tree
HIRCompileBase::compute_address_for_trait_item (
  const Resolver::TraitItemReference *ref,
  const TyTy::TypeBoundPredicate *predicate,
  std::vector<std::pair<Resolver::TraitReference *, HIR::ImplBlock *>>
    &receiver_bounds,
  const TyTy::BaseType *receiver, const TyTy::BaseType *root, location_t locus)
{
  TyTy::TypeBoundPredicateItem predicate_item
    = predicate->lookup_associated_item (ref->get_identifier ());
  rust_assert (!predicate_item.is_error ());

  // This is the expected end type
  TyTy::BaseType *trait_item_type = predicate_item.get_tyty_for_receiver (root);
  rust_assert (trait_item_type->get_kind () == TyTy::TypeKind::FNDEF);
  TyTy::FnType *trait_item_fntype
    = static_cast<TyTy::FnType *> (trait_item_type);

  // Loop through the list of trait references and impls that we satisfy.
  // We are looking for one that has an implementation for "ref", a trait
  // item.
  for (auto &item : receiver_bounds)
    {
      HIR::ImplBlock *impl_block = item.second;
      rust_assert (impl_block != nullptr);

      // Checks for empty impl blocks, triggered by Sized trait.
      if (!impl_block->has_type ())
	continue;

      // Lookup type for potentially associated impl.
      HIR::Type &self_type_path = impl_block->get_type ();

      // Convert HIR::Type to TyTy::BaseType
      TyTy::BaseType *self = nullptr;
      bool ok = ctx->get_tyctx ()->lookup_type (
	self_type_path.get_mappings ().get_hirid (), &self);

      rust_assert (ok);

      // Look through the relevant bounds on our type, and find which one our
      // impl block satisfies
      TyTy::TypeBoundPredicate *self_bound = nullptr;
      for (auto &bound : self->get_specified_bounds ())
	{
	  const Resolver::TraitReference *bound_ref = bound.get ();
	  const Resolver::TraitReference *specified_ref = predicate->get ();
	  // If this impl is for one of our types or supertypes
	  if (specified_ref->satisfies_bound (*bound_ref))
	    {
	      self_bound = &bound;
	      break;
	    }
	}

      // This impl block doesn't help us
      if (self_bound == nullptr)
	continue;

      // Find the specific function in the impl block that matches "ref".
      // This is the one we want to compute the address for.
      HIR::Function *associated_function = nullptr;
      for (auto &impl_item : impl_block->get_impl_items ())
	{
	  bool is_function = impl_item->get_impl_item_type ()
			     == HIR::ImplItem::ImplItemType::FUNCTION;
	  if (!is_function)
	    continue;

	  HIR::Function *fn = static_cast<HIR::Function *> (impl_item.get ());
	  bool found_associated_item
	    = fn->get_function_name ().as_string ().compare (
		ref->get_identifier ())
	      == 0;
	  if (found_associated_item)
	    associated_function = fn;
	}

      // This impl block satisfies the bound, but doesn't contain the relevant
      // function. This could happen because of supertraits.
      if (associated_function == nullptr)
	continue;

      // lookup the associated type for this item
      TyTy::BaseType *lookup = nullptr;
      ok = ctx->get_tyctx ()->lookup_type (
	associated_function->get_mappings ().get_hirid (), &lookup);
      rust_assert (ok);
      rust_assert (lookup->get_kind () == TyTy::TypeKind::FNDEF);
      TyTy::FnType *lookup_fntype = static_cast<TyTy::FnType *> (lookup);

      if (lookup_fntype->needs_substitution ())
	{
	  TyTy::BaseType *infer
	    = Resolver::SubstMapper::InferSubst (lookup_fntype, UNDEF_LOCATION);
	  infer
	    = Resolver::unify_site (infer->get_ref (),
				    TyTy::TyWithLocation (trait_item_fntype),
				    TyTy::TyWithLocation (infer),
				    UNDEF_LOCATION);
	  rust_assert (infer->get_kind () == TyTy::TypeKind::FNDEF);
	  lookup_fntype = static_cast<TyTy::FnType *> (infer);
	}

      return CompileInherentImplItem::Compile (associated_function, ctx,
					       lookup_fntype, locus);
    }

  // we can only compile trait-items with a body
  bool trait_item_has_definition = ref->is_optional ();
  rust_assert (trait_item_has_definition);

  HIR::TraitItem *trait_item = ref->get_hir_trait_item ();
  return CompileTraitItem::Compile (trait_item, ctx, trait_item_fntype, true,
				    locus);
}

bool
HIRCompileBase::verify_array_capacities (tree ltype, tree rtype,
					 location_t lvalue_locus,
					 location_t rvalue_locus)
{
  rust_assert (ltype != NULL_TREE);
  rust_assert (rtype != NULL_TREE);

  // lets just return ok as other errors have already occurred
  if (ltype == error_mark_node || rtype == error_mark_node)
    return true;

  tree ltype_domain = TYPE_DOMAIN (ltype);
  if (!ltype_domain)
    return false;

  if (!TREE_CONSTANT (TYPE_MAX_VALUE (ltype_domain)))
    return false;

  unsigned HOST_WIDE_INT ltype_length
    = wi::ext (wi::to_offset (TYPE_MAX_VALUE (ltype_domain))
		 - wi::to_offset (TYPE_MIN_VALUE (ltype_domain)) + 1,
	       TYPE_PRECISION (TREE_TYPE (ltype_domain)),
	       TYPE_SIGN (TREE_TYPE (ltype_domain)))
	.to_uhwi ();

  tree rtype_domain = TYPE_DOMAIN (rtype);
  if (!rtype_domain)
    return false;

  if (!TREE_CONSTANT (TYPE_MAX_VALUE (rtype_domain)))
    return false;

  unsigned HOST_WIDE_INT rtype_length
    = wi::ext (wi::to_offset (TYPE_MAX_VALUE (rtype_domain))
		 - wi::to_offset (TYPE_MIN_VALUE (rtype_domain)) + 1,
	       TYPE_PRECISION (TREE_TYPE (rtype_domain)),
	       TYPE_SIGN (TREE_TYPE (rtype_domain)))
	.to_uhwi ();

  if (ltype_length != rtype_length)
    {
      rust_error_at (rvalue_locus, ErrorCode::E0308,
		     "mismatched types, expected an array with a fixed size "
		     "of " HOST_WIDE_INT_PRINT_UNSIGNED
		     " elements, found one with " HOST_WIDE_INT_PRINT_UNSIGNED
		     " elements",
		     ltype_length, rtype_length);
      return false;
    }

  return true;
}

} // namespace Compile
} // namespace Rust
