/* PRU target specific passes
   Copyright (C) 2017-2021 Free Software Foundation, Inc.
   Dimitar Dimitrov <dimitar@dinux.eu>

   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/>.  */

#define IN_TARGET_CODE 1

#include "config.h"
#include "system.h"
#include "coretypes.h"
#include "backend.h"
#include "context.h"
#include "tm.h"
#include "alias.h"
#include "symtab.h"
#include "tree.h"
#include "diagnostic-core.h"
#include "function.h"
#include "gimple.h"
#include "gimple-iterator.h"
#include "gimple-walk.h"
#include "gimple-expr.h"
#include "tree-pass.h"

#include "pru-protos.h"

namespace {

/* Scan the tree to ensure that the compiled code by GCC
   conforms to the TI ABI specification.  If GCC cannot
   output a conforming code, raise an error.  */
const pass_data pass_data_tiabi_check =
{
  GIMPLE_PASS, /* type */
  "*tiabi_check", /* name */
  OPTGROUP_NONE, /* optinfo_flags */
  TV_NONE, /* tv_id */
  PROP_gimple_any, /* properties_required */
  0, /* properties_provided */
  0, /* properties_destroyed */
  0, /* todo_flags_start */
  0, /* todo_flags_finish */
};

/* Implementation class for the TI ABI compliance-check pass.  */
class pass_tiabi_check : public gimple_opt_pass
{
public:
  pass_tiabi_check (gcc::context *ctxt)
    : gimple_opt_pass (pass_data_tiabi_check, ctxt)
  {}

  /* opt_pass methods: */
  virtual unsigned int execute (function *);

  virtual bool gate (function *fun ATTRIBUTE_UNUSED)
  {
    return pru_current_abi == PRU_ABI_TI;
  }

}; // class pass_tiabi_check

/* Return 1 if type TYPE is a pointer to function type or a
   structure having a pointer to function type as one of its fields.
   Otherwise return 0.  */
static bool
chkp_type_has_function_pointer (const_tree type)
{
  bool res = false;

  if (POINTER_TYPE_P (type) && FUNC_OR_METHOD_TYPE_P (TREE_TYPE (type)))
    res = true;
  else if (RECORD_OR_UNION_TYPE_P (type))
    {
      tree field;

      for (field = TYPE_FIELDS (type); field; field = DECL_CHAIN (field))
	if (TREE_CODE (field) == FIELD_DECL)
	  res = res || chkp_type_has_function_pointer (TREE_TYPE (field));
    }
  else if (TREE_CODE (type) == ARRAY_TYPE)
    res = chkp_type_has_function_pointer (TREE_TYPE (type));

  return res;
}

/* Check the function declaration FNTYPE for TI ABI compatibility.  */
static void
chk_function_decl (const_tree fntype, location_t call_location)
{
  /* GCC does not check if the RETURN VALUE pointer is NULL,
     so do not allow GCC functions with large return values.  */
  if (!VOID_TYPE_P (TREE_TYPE (fntype))
      && pru_return_in_memory (TREE_TYPE (fntype), fntype))
    error_at (call_location,
	      "large return values not supported with %<-mabi=ti%> option");

  /* Check this function's arguments.  */
  for (tree p = TYPE_ARG_TYPES (fntype); p; p = TREE_CHAIN (p))
    {
      tree arg_type = TREE_VALUE (p);
      if (chkp_type_has_function_pointer (arg_type))
	error_at (call_location,
		  "function pointers not supported with %<-mabi=ti%> option");
    }
}

/* Callback for walk_gimple_seq that checks TP tree for TI ABI compliance.  */
static tree
check_op_callback (tree *tp, int *walk_subtrees, void *data)
{
  struct walk_stmt_info *wi = (struct walk_stmt_info *) data;

  if (RECORD_OR_UNION_TYPE_P (*tp) || TREE_CODE (*tp) == ENUMERAL_TYPE)
    {
      /* Forward declarations have NULL tree type.  Skip them.  */
      if (TREE_TYPE (*tp) == NULL)
	return NULL;
    }

  /* TODO - why C++ leaves INTEGER_TYPE forward declarations around?  */
  if (TREE_TYPE (*tp) == NULL)
    return NULL;

  const tree type = TREE_TYPE (*tp);

  /* Direct function calls are allowed, obviously.  */
  gcall *call = dyn_cast <gcall *> (gsi_stmt (wi->gsi));
  if (call
      && tp == gimple_call_fn_ptr (call)
      && gimple_call_fndecl (call))
    return NULL;

  switch (TREE_CODE (type))
    {
    case FUNCTION_TYPE:
    case METHOD_TYPE:
	{
	  /* Note: Do not enforce a small return value.  It is safe to
	     call any TI ABI function from GCC, since GCC will
	     never pass NULL.  */

	  /* Check arguments for function pointers.  */
	  for (tree p = TYPE_ARG_TYPES (type); p; p = TREE_CHAIN (p))
	    {
	      tree arg_type = TREE_VALUE (p);
	      if (chkp_type_has_function_pointer (arg_type))
		error_at (gimple_location (wi->stmt), "function pointers "
			  "not supported with %<-mabi=ti%> option");
	    }
	  break;
	}
    case RECORD_TYPE:
    case UNION_TYPE:
    case QUAL_UNION_TYPE:
    case POINTER_TYPE:
	{
	  if (chkp_type_has_function_pointer (type))
	    {
	      error_at (gimple_location (wi->stmt),
			"function pointers not supported with "
			"%<-mabi=ti%> option");
	      *walk_subtrees = false;
	    }
	  break;
	}
    default:
	  break;
    }
  return NULL;
}

/* Pass implementation.  */
unsigned
pass_tiabi_check::execute (function *fun)
{
  struct walk_stmt_info wi;
  const_tree fntype = TREE_TYPE (fun->decl);

  gimple_seq body = gimple_body (current_function_decl);

  memset (&wi, 0, sizeof (wi));
  wi.info = NULL;
  wi.want_locations = true;

  /* Check the function body.  */
  walk_gimple_seq (body, NULL, check_op_callback, &wi);

  /* Check the function declaration.  */
  chk_function_decl (fntype, fun->function_start_locus);

  return 0;
}

} // anon namespace

gimple_opt_pass *
make_pass_tiabi_check (gcc::context *ctxt)
{
  return new pass_tiabi_check (ctxt);
}

/* Register as early as possible.  */
void
pru_register_abicheck_pass (void)
{
  opt_pass *tiabi_check = make_pass_tiabi_check (g);
  struct register_pass_info tiabi_check_info
    = { tiabi_check, "*warn_unused_result",
	1, PASS_POS_INSERT_AFTER
      };
  register_pass (&tiabi_check_info);
}
