This is the mail archive of the
gcc@gcc.gnu.org
mailing list for the GCC project.
Re: [gomp] implement a handfull of easy directives
- From: Ian Lance Taylor <ian at airs dot com>
- To: Richard Henderson <rth at redhat dot com>
- Cc: gcc at gcc dot gnu dot org
- Date: 21 Sep 2005 21:35:54 -0700
- Subject: Re: [gomp] implement a handfull of easy directives
- References: <20050921234917.GA10871@redhat.com>
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