/* Callback attribute handling
   Copyright (C) 2025-2026 Free Software Foundation, Inc.
   Contributed by Josef Melcr <jmelcr@gcc.gnu.org>

   This file is part of GCC.

   GCC is free software; you can redistribute it and/or modify
   under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 3 of the License, 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 "config.h"
#include "system.h"
#include "coretypes.h"
#include "backend.h"
#include "tree.h"
#include "gimple.h"
#include "alloc-pool.h"
#include "cgraph.h"
#include "diagnostic.h"
#include "builtins.h"
#include "options.h"
#include "gimple-range.h"
#include "attribs.h"
#include "attr-callback.h"

/* Returns a callback attribute with callback index FN_IDX, and ARG_COUNT
   arguments specified by VA_ARGS.  */
tree
callback_build_attr (unsigned fn_idx, unsigned arg_count...)
{
  va_list args;
  va_start (args, arg_count);

  tree cblist = NULL_TREE;
  tree *pp = &cblist;
  unsigned i;
  for (i = 0; i < arg_count; i++)
    {
      int num = va_arg (args, int);
      tree tnum = build_int_cst (integer_type_node, num);
      *pp = build_tree_list (NULL, tnum);
      pp = &TREE_CHAIN (*pp);
    }
  cblist
    = tree_cons (NULL_TREE, build_int_cst (integer_type_node, fn_idx), cblist);
  tree attr
    = tree_cons (get_identifier (CALLBACK_ATTR_IDENT), cblist, NULL_TREE);
  return attr;
}

/* Returns TRUE if a function should be treated as if it had a callback
   attribute despite the DECL not having it.  STMT can be passed NULL
   if the call statement is not available at the time, for example WPA, but it
   should be called with the statement itself whenever possible.  */
bool
callback_is_special_cased (tree decl, gcall *stmt)
{
  if (fndecl_built_in_p (decl, BUILT_IN_GOMP_TASK))
    {
      if (stmt)
	return gimple_call_arg (stmt, 2) == null_pointer_node;
      return true;
    }
  return false;
}

/* Returns an attribute for a special cased function.  */
tree
callback_special_case_attr (tree decl)
{
  if (fndecl_built_in_p (decl, BUILT_IN_GOMP_TASK))
    return callback_build_attr (1, 1, 2);
  gcc_unreachable ();
}

/* Returns TRUE if the callee of E has a callback attribute.  */
bool
callback_edge_callee_has_attr (cgraph_edge *e)
{
  return lookup_attribute (CALLBACK_ATTR_IDENT,
			   DECL_ATTRIBUTES (e->callee->decl))
	 || callback_is_special_cased (e->callee->decl, e->call_stmt);
}

/* Given an instance of callback attribute, return the 0-based
   index of the called function in question.  */
int
callback_get_fn_index (tree cb_attr)
{
  tree args = TREE_VALUE (cb_attr);
  int idx = TREE_INT_CST_LOW (TREE_VALUE (args)) - 1;
  return idx;
}

/* For a given callback pair, retrieves the callback attribute used
   to create E from the callee of CARRYING.  */
tree
callback_fetch_attr_by_edge (cgraph_edge *e, cgraph_edge *carrying)
{
  gcc_checking_assert (e->call_stmt == carrying->call_stmt
		       && e->lto_stmt_uid == carrying->lto_stmt_uid);

  if (callback_is_special_cased (carrying->callee->decl, e->call_stmt))
    return callback_special_case_attr (carrying->callee->decl);

  tree cb_attr = lookup_attribute (CALLBACK_ATTR_IDENT,
				   DECL_ATTRIBUTES (carrying->callee->decl));
  gcc_checking_assert (cb_attr);
  tree res = NULL_TREE;
  for (; cb_attr;
       cb_attr = lookup_attribute (CALLBACK_ATTR_IDENT, TREE_CHAIN (cb_attr)))
    {
      unsigned id = callback_get_fn_index (cb_attr);
      if (id == e->callback_id)
	{
	  res = cb_attr;
	  break;
	}
    }
  gcc_checking_assert (res != NULL_TREE);
  return res;
}

/* Given an instance of callback attribute, return the 0-base indices
   of arguments passed to the callback.  For a callback function taking
   n parameters, returns a vector of n indices of their values in the parameter
   list of it's caller.  Indices with unknown positions contain -1.  */
auto_vec<int>
callback_get_arg_mapping (cgraph_edge *e, cgraph_edge *carrying)
{
  tree attr = callback_fetch_attr_by_edge (e, carrying);
  gcc_checking_assert (attr);
  tree args = TREE_VALUE (attr);
  auto_vec<int> res;
  tree it;

  /* Skip over the first argument, which denotes
     which argument is the called function.  */
  for (it = TREE_CHAIN (args); it != NULL_TREE; it = TREE_CHAIN (it))
    {
      int idx = TREE_INT_CST_LOW (TREE_VALUE (it));
      /* Subtract 1 to account for 1-based indexing.  If the value is unknown,
	 use constant -1 instead.  */
      idx = idx == CB_UNKNOWN_POS ? -1 : idx - 1;
      res.safe_push (idx);
    }

  return res;
}

/* For a callback pair, returns the 0-based index of the address of
   E's callee in the argument list of CARRYING's callee decl.  */
int
callback_fetch_fn_position (cgraph_edge *e, cgraph_edge *carrying)
{
  tree attr = callback_fetch_attr_by_edge (e, carrying);
  return callback_get_fn_index (attr);
}

/* Returns the element at index idx in the list or NULL_TREE if
   the list isn't long enough.  NULL_TREE is used as the endpoint.  */
static tree
get_nth_list_elem (tree list, unsigned idx)
{
  tree res = NULL_TREE;
  unsigned i = 0;
  tree it;
  for (it = list; it != NULL_TREE; it = TREE_CHAIN (it), i++)
    {
      if (i == idx)
	{
	  res = TREE_VALUE (it);
	  break;
	}
    }
  return res;
}

/* Handle a "callback" attribute; arguments as in
   struct attribute_spec.handler.  */
tree
handle_callback_attribute (tree *node, tree name, tree args,
			   int ARG_UNUSED (flags), bool *no_add_attrs)
{
  tree decl = *node;
  if (TREE_CODE (decl) != FUNCTION_DECL)
    {
      error_at (DECL_SOURCE_LOCATION (decl),
		"%qE attribute can only be used on functions", name);
      *no_add_attrs = true;
    }

  tree cb_fn_idx_node = TREE_VALUE (args);
  if (TREE_CODE (cb_fn_idx_node) != INTEGER_CST)
    {
      error_at (DECL_SOURCE_LOCATION (decl),
		"argument specifying callback function position is not an "
		"integer constant");
      *no_add_attrs = true;
      return NULL_TREE;
    }
  /* We have to use the function type for validation, as
     DECL_ARGUMENTS returns NULL at this point.  */
  int callback_fn_idx = TREE_INT_CST_LOW (cb_fn_idx_node);
  tree decl_type_args = TYPE_ARG_TYPES (TREE_TYPE (decl));
  tree it;
  int decl_nargs = list_length (decl_type_args);
  for (it = decl_type_args; it != NULL_TREE; it = TREE_CHAIN (it))
    if (it == void_list_node)
      {
	--decl_nargs;
	break;
      }
  if (callback_fn_idx == CB_UNKNOWN_POS)
    {
      error_at (DECL_SOURCE_LOCATION (decl),
		"callback function position cannot be marked as unknown");
      *no_add_attrs = true;
      return NULL_TREE;
    }
  --callback_fn_idx;
  if (callback_fn_idx >= decl_nargs)
    {
      error_at (DECL_SOURCE_LOCATION (decl),
		"callback function position out of range");
      *no_add_attrs = true;
      return NULL_TREE;
    }

  /* Search for the type of the callback function
     in parameters of the original function.  */
  tree cfn = get_nth_list_elem (decl_type_args, callback_fn_idx);
  if (cfn == NULL_TREE)
    {
      error_at (DECL_SOURCE_LOCATION (decl),
		"could not retrieve callback function from arguments");
      *no_add_attrs = true;
      return NULL_TREE;
    }
  tree cfn_pointee_type = TREE_TYPE (cfn);
  if (TREE_CODE (cfn) != POINTER_TYPE
      || TREE_CODE (cfn_pointee_type) != FUNCTION_TYPE)
    {
      error_at (DECL_SOURCE_LOCATION (decl),
		"argument no. %d is not an address of a function",
		callback_fn_idx + 1);
      *no_add_attrs = true;
      return NULL_TREE;
    }

  tree type_args = TYPE_ARG_TYPES (cfn_pointee_type);
  /* Compare the length of the list of argument indices
     and the real number of parameters the callback takes.  */
  unsigned cfn_nargs = list_length (TREE_CHAIN (args));
  unsigned type_nargs = list_length (type_args);
  for (it = type_args; it != NULL_TREE; it = TREE_CHAIN (it))
    if (it == void_list_node)
      {
	--type_nargs;
	break;
      }
  if (cfn_nargs != type_nargs)
    {
      error_at (DECL_SOURCE_LOCATION (decl),
		"argument number mismatch, %d expected, got %d", type_nargs,
		cfn_nargs);
      *no_add_attrs = true;
      return NULL_TREE;
    }

  unsigned curr = 0;
  tree cfn_it;
  /* Validate type compatibility of the arguments passed
     from caller function to callback.  "it" is used to step
     through the parameters of the caller, "cfn_it" is
     stepping through the parameters of the callback.  */
  for (it = type_args, cfn_it = TREE_CHAIN (args); curr < type_nargs;
       it = TREE_CHAIN (it), cfn_it = TREE_CHAIN (cfn_it), curr++)
    {
      if (TREE_CODE (TREE_VALUE (cfn_it)) != INTEGER_CST)
	{
	  error_at (DECL_SOURCE_LOCATION (decl),
		    "argument no. %d is not an integer constant", curr + 1);
	  *no_add_attrs = true;
	  continue;
	}

      int arg_idx = TREE_INT_CST_LOW (TREE_VALUE (cfn_it));

      /* No need to check for type compatibility,
	 if we don't know what we are passing.  */
      if (arg_idx == CB_UNKNOWN_POS)
	continue;

      arg_idx -= 1;
      /* Report an error if the position is out of bounds,
	 but we can still check the rest of the arguments.  */
      if (arg_idx >= decl_nargs)
	{
	  error_at (DECL_SOURCE_LOCATION (decl),
		    "callback argument index %d is out of range", arg_idx + 1);
	  *no_add_attrs = true;
	  continue;
	}

      tree arg_type = get_nth_list_elem (decl_type_args, arg_idx);
      tree expected_type = TREE_VALUE (it);
      /* Check the type of the value we are about to pass ("arg_type")
	 for compatibility with the actual type the callback function
	 expects ("expected_type").  */
      if (!types_compatible_p (expected_type, arg_type))
	{
	  error_at (DECL_SOURCE_LOCATION (decl),
		    "argument type at index %d is not compatible with callback "
		    "argument type at index %d",
		    arg_idx + 1, curr + 1);
	  *no_add_attrs = true;
	  continue;
	}
    }

  /* Check that the decl does not already have a callback attribute describing
     the same argument.  */
  it = lookup_attribute (CALLBACK_ATTR_IDENT, DECL_ATTRIBUTES (decl));
  for (; it; it = lookup_attribute (CALLBACK_ATTR_IDENT, TREE_CHAIN (it)))
    if (callback_get_fn_index (it) == callback_fn_idx)
      {
	error_at (DECL_SOURCE_LOCATION (decl),
		  "function declaration has multiple callback attributes "
		  "describing argument no. %d",
		  callback_fn_idx + 1);
	*no_add_attrs = true;
	break;
      }

  return NULL_TREE;
}

/* Returns TRUE if E is considered useful in the callgraph, FALSE otherwise.  If
   this predicate returns FALSE, then E wasn't used to optimize its callee and
   can be safely removed from the callgraph.  */
bool
callback_edge_useful_p (cgraph_edge *e)
{
  gcc_checking_assert (e->callback);
  /* If the edge is pointing towards a clone, it is useful.  */
  if (e->callee->clone_of)
    return true;

  /* If the callee has been produced by icf, the edge is useful, as it will be
     used to for the redirection.  */
  if (e->callee->icf_merged)
    return true;

  /* In case some future pass redirects edges, it should be added as a case
     here.  */

  return false;
}

/* Returns the number of arguments the callback function described by ATTR
   takes.  */

size_t
callback_num_args (tree attr)
{
  tree args = TREE_VALUE (attr);
  size_t res = 0;
  tree it;

  for (it = TREE_CHAIN (args); it != NULL_TREE; it = TREE_CHAIN (it), ++res)
    ;
  return res;
}
