/* Support for plugin-supplied behaviors of known functions.
   Copyright (C) 2022-2026 Free Software Foundation, Inc.
   Contributed by David Malcolm <dmalcolm@redhat.com>.

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 "analyzer/common.h"

#include "diagnostic-core.h"
#include "stringpool.h"

#include "analyzer/analyzer-logging.h"
#include "analyzer/known-function-manager.h"
#include "analyzer/region-model.h"
#include "analyzer/call-details.h"

#if ENABLE_ANALYZER

namespace ana {

/* class known_function_manager : public log_user.  */

known_function_manager::known_function_manager (logger *logger)
: log_user (logger)
{
  memset (m_combined_fns_arr, 0, sizeof (m_combined_fns_arr));
}

known_function_manager::~known_function_manager ()
{
  /* Delete all owned kfs.  */
  for (auto iter : m_map_id_to_kf)
    delete iter.second;
  for (auto iter : m_std_ns_map_id_to_kf)
    delete iter.second;
  for (auto iter : m_combined_fns_arr)
    delete iter;
}

void
known_function_manager::add (const char *name,
			     std::unique_ptr<known_function> kf)
{
  LOG_FUNC_1 (get_logger (), "registering %s", name);
  tree id = get_identifier (name);
  m_map_id_to_kf.put (id, kf.release ());
}

void
known_function_manager::add_std_ns (const char *name,
			     std::unique_ptr<known_function> kf)
{
  LOG_FUNC_1 (get_logger (), "registering std::%s", name);
  tree id = get_identifier (name);
  m_std_ns_map_id_to_kf.put (id, kf.release ());
}

void
known_function_manager::add (enum built_in_function name,
			     std::unique_ptr<known_function> kf)
{
  gcc_assert (name < END_BUILTINS);
  delete m_combined_fns_arr[name];
  m_combined_fns_arr[name] = kf.release ();
}

void
known_function_manager::add (enum internal_fn ifn,
			     std::unique_ptr<known_function> kf)
{
  gcc_assert (ifn < IFN_LAST);
  delete m_combined_fns_arr[ifn + int (END_BUILTINS)];
  m_combined_fns_arr[ifn + int (END_BUILTINS)] = kf.release ();
}

/* Get any known_function for FNDECL for call CD.

   The call must match all assumptions made by the known_function (such as
   e.g. "argument 1's type must be a pointer type").

   Return nullptr if no known_function is found, or it does not match the
   assumption(s).  */

const known_function *
known_function_manager::get_match (tree fndecl, const call_details &cd) const
{
  /* Look for a matching built-in.  */
  if (fndecl_built_in_p (fndecl, BUILT_IN_NORMAL))
    {
      if (const known_function *candidate
	  = get_normal_builtin (DECL_FUNCTION_CODE (fndecl)))
	if (gimple_builtin_call_types_compatible_p (&cd.get_call_stmt (),
						    fndecl))
	  return candidate;
    }

  /* Look for a match by name.  */

  if (is_std_function_p (fndecl))
    {
      if (tree identifier = DECL_NAME (fndecl))
	if (const known_function *candidate
	      = get_by_identifier_in_std_ns (identifier))
	  if (candidate->matches_call_types_p (cd))
	    return candidate;
      return nullptr;
    }

  /* Only match functions declared at global scope, or within namespace
     __cxxabiv1 (e.g. __dynamic_cast).  */
  if (!is_cxxabi_function_p (fndecl))
    if (DECL_CONTEXT (fndecl)
	&& TREE_CODE (DECL_CONTEXT (fndecl)) != TRANSLATION_UNIT_DECL)
      return nullptr;

  if (tree identifier = DECL_NAME (fndecl))
    if (const known_function *candidate = get_by_identifier (identifier))
      if (candidate->matches_call_types_p (cd))
	return candidate;

  return nullptr;
}

/* Get any known_function for IFN, or nullptr.  */

const known_function *
known_function_manager::get_internal_fn (enum internal_fn ifn) const
{
  gcc_assert (ifn < IFN_LAST);
  return m_combined_fns_arr[ifn + int (END_BUILTINS)];
}

/* Get any known_function for NAME, without type-checking.
   Return nullptr if there isn't one.  */

const known_function *
known_function_manager::get_normal_builtin (enum built_in_function name) const
{
  /* The numbers for built-in functions in enum combined_fn are the same as
     for the built_in_function enum.  */
  gcc_assert (name < END_BUILTINS);
  return m_combined_fns_arr[name];
}

const known_function *
known_function_manager::
get_normal_builtin (const builtin_known_function *builtin_kf) const
{
  return get_normal_builtin (builtin_kf->builtin_code ());
}

/* Get any known_function matching IDENTIFIER, without type-checking.
   Return nullptr if there isn't one.  */

const known_function *
known_function_manager::get_by_identifier (tree identifier) const
{
  known_function_manager *mut_this = const_cast<known_function_manager *>(this);
  known_function **slot = mut_this->m_map_id_to_kf.get (identifier);
  if (slot)
    return *slot;
  else
    return nullptr;
}

/* Get any known_function in C++ std:: namespace matching IDENTIFIER, without
   type-checking.
   Return nullptr if there isn't one.  */

const known_function *
known_function_manager::get_by_identifier_in_std_ns (tree identifier) const
{
  known_function_manager *mut_this = const_cast<known_function_manager *>(this);
  known_function **slot = mut_this->m_std_ns_map_id_to_kf.get (identifier);
  if (slot)
    return *slot;
  else
    return nullptr;
}

static std::unique_ptr<json::array>
get_keys_as_json (const hash_map<tree, known_function *> &map)
{
  std::vector<std::string> vec_keys;
  for (const auto &iter : map)
    vec_keys.push_back (IDENTIFIER_POINTER (iter.first));

  std::sort (vec_keys.begin (), vec_keys.end ());

  auto arr = std::make_unique<json::array> ();
  for (auto iter : vec_keys)
    arr->append_string (iter.c_str ());
  return arr;
}

std::unique_ptr<json::object>
known_function_manager::to_json () const
{
  auto obj = std::make_unique<json::object> ();

  obj->set ("root_ns", get_keys_as_json (m_map_id_to_kf));
  obj->set ("std_ns", get_keys_as_json (m_std_ns_map_id_to_kf));

  // Built-in functions
  // TODO: needs bulletproofing of combined_fn_name
  if (0)
    {
      std::vector<std::string> vec_keys;
      for (int i = 0; i < CFN_LAST; ++i)
	if (m_combined_fns_arr[i])
	  vec_keys.push_back
	    (combined_fn_name (static_cast<enum combined_fn> (i)));

      std::sort (vec_keys.begin (), vec_keys.end ());

      auto arr = std::make_unique<json::array> ();
      for (auto iter : vec_keys)
	arr->append_string (iter.c_str ());
      obj->set ("builtin_fns", std::move (arr));
    }

  return obj;
}


} // namespace ana

#endif /* #if ENABLE_ANALYZER */
