This is the mail archive of the gcc@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [gomp] implement a handfull of easy directives


Richard Henderson <rth@redhat.com> writes:

> 	* builtin-types.def (BT_PTR_LONG, BT_PTR_PTR, BT_FN_BOOL, BT_FN_INT,
> 	BT_FN_VOID_PTRPTR, BT_PTR_FN_VOID_PTR, BT_FN_VOID_UINT_UINT,
> 	BT_FN_BOOL_LONGPTR_LONGPTR, BT_FN_VOID_OMPFN_PTR_UINT,
> 	BT_FN_VOID_OMPFN_PTR_UINT_UINT,
> 	BT_FN_BOOL_LONG_LONG_LONG_LONGPTR_LONGPTR,
> 	BT_FN_BOOL_LONG_LONG_LONG_LONG_LONGPTR_LONGPTR,
> 	BT_FN_VOID_OMPFN_PTR_UINT_LONG_LONG_LONG,
> 	BT_FN_VOID_OMPFN_PTR_UINT_LONG_LONG_LONG_LONG): New.

I'm working on a target with two gazillion special builtins (well, a
few hundred) and I got tired of defining a new special type every time
I wanted to define a different builtin.  So I did this, slightly
simplified:

enum c2_builtin_type
{
  C2_INT,	/* int */
  C2_SHORT,	/* short */
  C2_CHAR,	/* char */
  C2_VPTR,	/* void * */
  C2_VOID,	/* void */
  /* plus other weird types */
  C2_NONE,	/* indicates no type */
  C2_MAX
};

struct builtin_description
{
  /* The code for this function.  */
  int icode;

  /* The name of the builtin function.  */
  const char *name;

  /* Code for return type.  */
  enum c2_builtin_type ret_type;

  /* Code for parameter types.  */
  enum c2_builtin_type param_types[6];
};

  tree btypes[C2_MAX];
  struct ftype_cache
  {
    tree fn_type;
    struct ftype_cache *next_arg[C2_MAX];
  } ftypes;

  btypes[C2_INT] = integer_type_node;
  btypes[C2_SHORT] = short_integer_type_node;
  btypes[C2_CHAR] = char_type_node;
  btypes[C2_VPTR] = ptr_type_node;
  btypes[C2_VOID] = void_type_node;
  btypes[C2_NONE] = NULL_TREE;

(plus all the other weird types)

  for (i = 0; i < ARRAY_SIZE (builtins); ++i)
    {
      const struct builtin_description *p;
      struct ftype_cache **pf;
      unsigned int j;

      p = &builtins[i];

      /* We cache the function type when we build it so that we don't
	 duplicate function types unnecessarily.  */

      gcc_assert (btypes[p->ret_type] != NULL_TREE);
      pf = &ftypes.next_arg[p->ret_type];
      for (j = 0; j < 6; ++j)
	{
	  if (*pf == NULL)
	    {
	      *pf = alloca (sizeof (struct ftype_cache));
	      memset (*pf, 0, sizeof (struct ftype_cache));
	    }
	  if (p->param_types[j] == C2_NONE)
	    break;
	  gcc_assert (btypes[p->param_types[j]] != NULL_TREE);
	  pf = &(*pf)->next_arg[p->param_types[j]];
	}

      if (*pf == NULL)
	{
	  *pf = alloca (sizeof (struct ftype_cache));
	  memset (*pf, 0, sizeof (struct ftype_cache));
	}

      if ((*pf)->fn_type == NULL)
	{
	  gcc_assert (p->ret_type != C2_NONE);
	  (*pf)->fn_type = build_function_type_list (btypes[p->ret_type],
						     btypes[p->param_types[0]],
						     btypes[p->param_types[1]],
						     btypes[p->param_types[2]],
						     btypes[p->param_types[3]],
						     btypes[p->param_types[4]],
						     btypes[p->param_types[5]],
						     NULL_TREE);
	}

      lang_hooks.builtin_function (p->name, (*pf)->fn_type,
				   p->icode, BUILT_IN_MD,
				   NULL, NULL);
    }

The builtins table is initialized with a separate .def file, but it
boils down to initializers this:

  { code, "__builtin_name", C2_INT,
   { C2_INT, C2_VPTR, C2_NONE, C2_NONE, C2_NONE, C2_NONE } },

This way I only have to write the type in one place, I only create the
function types I need, and the types are cached so I don't create the
same type more than once.

Much simpler in the long run, I think.

(And this is why I needed this patch:

2005-02-11  Ian Lance Taylor  <ian@airs.com>

	* tree.c (build_function_type_list): Work correctly if there are
	no arguments.

for the case of a builtin which takes no parameters, for which we wind
up calling build_function_type_list (NULL_TREE, NULL_TREE, ....).)

Ian


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]