This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[gfortran] Builtin functions
- From: Paul Brook <paul at nowt dot org>
- To: "gcc-g95 List" <gcc-g95-devel at lists dot sourceforge dot net>
- Cc: "gcc-patches at gcc dot gnu dot org" <gcc-patches at gcc dot gnu dot org>
- Date: Sat, 30 Aug 2003 19:00:11 +0100
- Subject: [gfortran] Builtin functions
The attached patch maked gfortran handle builtin functions that same way as
java and g77. It avoids having to deal with all the messy c-specific mess
associated with using builtins.def.
Applied to tree-ssa branch.
I'll post a followup patch to revert the signed_size_type hack once it's
tested.
Paul
2003-08-30 Paul Brook <paul@nowt.org>
* f95-lang.c (builtin_function): Remove #if 0 code.
(gfc_define_builtin): New function.
(gfc_init_builtin_functions): Use mathbuiltins.def not ../builtins.def.
* mathbuiltins.def: New file.
* trans-intrinsic.c (gfc_intrinsic_map_t): Add builtin code fields.
(gfc_intrinsic_map): Use mathbuiltins.def.
(gfc_intrinsic_builtin_t): Remove.
(gfc_build_intrinsic_lib_fndecls): Update.
* trans-types.c (gfc_init_types): Remove redundant initilaization of
signed_size_type_node.
diff -uNprxCVS clean/tree-ssa/gcc/fortran/f95-lang.c gcc/gcc/fortran/f95-lang.c
--- clean/tree-ssa/gcc/fortran/f95-lang.c 2003-07-26 00:07:31.000000000 +0100
+++ gcc/gcc/fortran/f95-lang.c 2003-08-30 18:28:40.000000000 +0100
@@ -815,7 +815,8 @@ builtin_function (const char *name,
tree type,
int function_code,
enum built_in_class class,
- const char *library_name, tree attrs ATTRIBUTE_UNUSED)
+ const char *library_name,
+ tree attrs ATTRIBUTE_UNUSED)
{
tree decl = build_decl (FUNCTION_DECL, get_identifier (name), type);
DECL_EXTERNAL (decl) = 1;
@@ -826,197 +827,80 @@ builtin_function (const char *name,
pushdecl (decl);
DECL_BUILT_IN_CLASS (decl) = class;
DECL_FUNCTION_CODE (decl) = function_code;
-
-#if 0
- if (attrs)
- decl_attributes (&decl, attrs, ATTR_FLAG_BUILT_IN);
- else
- decl_attributes (&decl, NULL_TREE, 0);
-#endif
return decl;
}
-#define flag_isoc99 0
-enum built_in_attribute
+
+static void
+gfc_define_builtin (const char * name,
+ tree type,
+ int code,
+ const char * library_name)
{
-#define DEF_ATTR_NULL_TREE(ENUM) ENUM,
-#define DEF_ATTR_INT(ENUM, VALUE) ENUM,
-#define DEF_ATTR_IDENT(ENUM, STRING) ENUM,
-#define DEF_ATTR_TREE_LIST(ENUM, PURPOSE, VALUE, CHAIN) ENUM,
-#define DEF_FN_ATTR(NAME, ATTRS, PREDICATE) /* No entry needed in enum. */
-#include "builtin-attrs.def"
-#undef DEF_ATTR_NULL_TREE
-#undef DEF_ATTR_INT
-#undef DEF_ATTR_IDENT
-#undef DEF_ATTR_TREE_LIST
-#undef DEF_FN_ATTR
- ATTR_LAST
-};
+ built_in_decls[code] = builtin_function (name, type, code, BUILT_IN_NORMAL,
+ library_name, NULL_TREE);
+}
-/* Initialisation of builtin function nodes. Copied from c-common.c. */
+
+#define DEFINE_MATH_BUILTIN(code, name, nargs) \
+ gfc_define_builtin ("__builtin_" name, mfunc_double[nargs], \
+ BUILT_IN_ ## code, name); \
+ gfc_define_builtin ("__builtin_" name "f", mfunc_float[nargs], \
+ BUILT_IN_ ## code ## F, name "f");
+
+/* Initialisation of builtin function nodes. */
static void
gfc_init_builtin_functions (void)
{
- enum builtin_type
- {
-#define DEF_PRIMITIVE_TYPE(NAME, VALUE) NAME,
-#define DEF_FUNCTION_TYPE_0(NAME, RETURN) NAME,
-#define DEF_FUNCTION_TYPE_1(NAME, RETURN, ARG1) NAME,
-#define DEF_FUNCTION_TYPE_2(NAME, RETURN, ARG1, ARG2) NAME,
-#define DEF_FUNCTION_TYPE_3(NAME, RETURN, ARG1, ARG2, ARG3) NAME,
-#define DEF_FUNCTION_TYPE_4(NAME, RETURN, ARG1, ARG2, ARG3, ARG4) NAME,
-#define DEF_FUNCTION_TYPE_VAR_0(NAME, RETURN) NAME,
-#define DEF_FUNCTION_TYPE_VAR_1(NAME, RETURN, ARG1) NAME,
-#define DEF_FUNCTION_TYPE_VAR_2(NAME, RETURN, ARG1, ARG2) NAME,
-#define DEF_FUNCTION_TYPE_VAR_3(NAME, RETURN, ARG1, ARG2, ARG3) NAME,
-#define DEF_POINTER_TYPE(NAME, TYPE) NAME,
-#include "builtin-types.def"
-#undef DEF_PRIMITIVE_TYPE
-#undef DEF_FUNCTION_TYPE_0
-#undef DEF_FUNCTION_TYPE_1
-#undef DEF_FUNCTION_TYPE_2
-#undef DEF_FUNCTION_TYPE_3
-#undef DEF_FUNCTION_TYPE_4
-#undef DEF_FUNCTION_TYPE_VAR_0
-#undef DEF_FUNCTION_TYPE_VAR_1
-#undef DEF_FUNCTION_TYPE_VAR_2
-#undef DEF_FUNCTION_TYPE_VAR_3
-#undef DEF_POINTER_TYPE
- BT_LAST
- };
-
- typedef enum builtin_type builtin_type;
-
- tree builtin_types[(int) BT_LAST];
- tree va_list_ref_type_node;
- tree va_list_arg_type_node;
-
- if (TREE_CODE (va_list_type_node) == ARRAY_TYPE)
- {
- va_list_arg_type_node = va_list_ref_type_node =
- build_pointer_type (TREE_TYPE (va_list_type_node));
- }
- else
- {
- va_list_arg_type_node = va_list_type_node;
- va_list_ref_type_node = build_reference_type (va_list_type_node);
- }
-
-#define DEF_PRIMITIVE_TYPE(ENUM, VALUE) \
- builtin_types[(int) ENUM] = VALUE;
-#define DEF_FUNCTION_TYPE_0(ENUM, RETURN) \
- builtin_types[(int) ENUM] \
- = build_function_type (builtin_types[(int) RETURN], \
- void_list_node);
-#define DEF_FUNCTION_TYPE_1(ENUM, RETURN, ARG1) \
- builtin_types[(int) ENUM] \
- = build_function_type (builtin_types[(int) RETURN], \
- tree_cons (NULL_TREE, \
- builtin_types[(int) ARG1], \
- void_list_node));
-#define DEF_FUNCTION_TYPE_2(ENUM, RETURN, ARG1, ARG2) \
- builtin_types[(int) ENUM] \
- = build_function_type \
- (builtin_types[(int) RETURN], \
- tree_cons (NULL_TREE, \
- builtin_types[(int) ARG1], \
- tree_cons (NULL_TREE, \
- builtin_types[(int) ARG2], \
- void_list_node)));
-#define DEF_FUNCTION_TYPE_3(ENUM, RETURN, ARG1, ARG2, ARG3) \
- builtin_types[(int) ENUM] \
- = build_function_type \
- (builtin_types[(int) RETURN], \
- tree_cons (NULL_TREE, \
- builtin_types[(int) ARG1], \
- tree_cons (NULL_TREE, \
- builtin_types[(int) ARG2], \
- tree_cons (NULL_TREE, \
- builtin_types[(int) ARG3], \
- void_list_node))));
-#define DEF_FUNCTION_TYPE_4(ENUM, RETURN, ARG1, ARG2, ARG3, ARG4) \
- builtin_types[(int) ENUM] \
- = build_function_type \
- (builtin_types[(int) RETURN], \
- tree_cons (NULL_TREE, \
- builtin_types[(int) ARG1], \
- tree_cons (NULL_TREE, \
- builtin_types[(int) ARG2], \
- tree_cons \
- (NULL_TREE, \
- builtin_types[(int) ARG3], \
- tree_cons (NULL_TREE, \
- builtin_types[(int) ARG4], \
- void_list_node)))));
-#define DEF_FUNCTION_TYPE_VAR_0(ENUM, RETURN) \
- builtin_types[(int) ENUM] \
- = build_function_type (builtin_types[(int) RETURN], NULL_TREE);
-#define DEF_FUNCTION_TYPE_VAR_1(ENUM, RETURN, ARG1) \
- builtin_types[(int) ENUM] \
- = build_function_type (builtin_types[(int) RETURN], \
- tree_cons (NULL_TREE, \
- builtin_types[(int) ARG1], \
- NULL_TREE));
-
-#define DEF_FUNCTION_TYPE_VAR_2(ENUM, RETURN, ARG1, ARG2) \
- builtin_types[(int) ENUM] \
- = build_function_type \
- (builtin_types[(int) RETURN], \
- tree_cons (NULL_TREE, \
- builtin_types[(int) ARG1], \
- tree_cons (NULL_TREE, \
- builtin_types[(int) ARG2], \
- NULL_TREE)));
-
-#define DEF_FUNCTION_TYPE_VAR_3(ENUM, RETURN, ARG1, ARG2, ARG3) \
- builtin_types[(int) ENUM] \
- = build_function_type \
- (builtin_types[(int) RETURN], \
- tree_cons (NULL_TREE, \
- builtin_types[(int) ARG1], \
- tree_cons (NULL_TREE, \
- builtin_types[(int) ARG2], \
- tree_cons (NULL_TREE, \
- builtin_types[(int) ARG3], \
- NULL_TREE))));
-#define DEF_POINTER_TYPE(ENUM, TYPE) \
- builtin_types[(int) ENUM] \
- = build_pointer_type (builtin_types[(int) TYPE]);
-#include "builtin-types.def"
-#undef DEF_PRIMITIVE_TYPE
-#undef DEF_FUNCTION_TYPE_1
-#undef DEF_FUNCTION_TYPE_2
-#undef DEF_FUNCTION_TYPE_3
-#undef DEF_FUNCTION_TYPE_4
-#undef DEF_FUNCTION_TYPE_VAR_0
-#undef DEF_FUNCTION_TYPE_VAR_1
-#undef DEF_FUNCTION_TYPE_VAR_2
-#undef DEF_FUNCTION_TYPE_VAR_3
-#undef DEF_POINTER_TYPE
-
-#define DEF_BUILTIN(ENUM, NAME, CLASS, TYPE, LIBTYPE, \
- BOTH_P, FALLBACK_P, NONANSI_P, ATTRS, IMPLICIT) \
- if (NAME) \
- { \
- tree decl; \
- \
- if (strncmp (NAME, "__builtin_", strlen ("__builtin_")) != 0) \
- abort (); \
- \
- decl = builtin_function (NAME, builtin_types[TYPE], ENUM, \
- CLASS, \
- (FALLBACK_P \
- ? (NAME + strlen ("__builtin_")) \
- : NULL), \
- NULL); \
- \
- built_in_decls[(int) ENUM] = decl; \
- }
-#include "builtins.def"
-#undef DEF_BUILTIN
-
- main_identifier_node = get_identifier ("main");
+ tree mfunc_float[2];
+ tree mfunc_double[2];
+ tree ftype_expect;
+ tree ftype_memcpy;
+ tree tmp;
+ tree voidchain;
+
+ voidchain = tree_cons (NULL_TREE, void_type_node, NULL_TREE);
+
+ tmp = tree_cons (NULL_TREE, float_type_node, voidchain);
+ mfunc_float[1] = build_function_type (float_type_node, tmp);
+ tmp = tree_cons (NULL_TREE, float_type_node, tmp);
+ mfunc_float[2] = build_function_type (float_type_node, tmp);
+
+ tmp = tree_cons (NULL_TREE, double_type_node, voidchain);
+ mfunc_double[1] = build_function_type (double_type_node, tmp);
+ tmp = tree_cons (NULL_TREE, double_type_node, tmp);
+ mfunc_double[2] = build_function_type (double_type_node, tmp);
+
+ tmp = tree_cons (NULL_TREE, long_integer_type_node, voidchain);
+ tmp = tree_cons (NULL_TREE, long_integer_type_node, tmp);
+ ftype_expect = build_function_type (long_integer_type_node, tmp);
+
+ tmp = tree_cons (NULL_TREE, size_type_node, voidchain);
+ tmp = tree_cons (NULL_TREE, pvoid_type_node, voidchain);
+ tmp = tree_cons (NULL_TREE, pvoid_type_node, voidchain);
+ ftype_memcpy = build_function_type (pvoid_type_node, tmp);
+
+#include "mathbuiltins.def"
+
+ /* We define there seperately as the fortran versions have different
+ semantics (they return an integer type) */
+ gfc_define_builtin ("__builtin_floor", mfunc_double[1],
+ BUILT_IN_FLOOR, "floor");
+ gfc_define_builtin ("__builtin_floorf", mfunc_float[1],
+ BUILT_IN_FLOORF, "floorf");
+ gfc_define_builtin ("__builtin_round", mfunc_double[1],
+ BUILT_IN_ROUND, "round");
+ gfc_define_builtin ("__builtin_roundf", mfunc_float[1],
+ BUILT_IN_ROUNDF, "roundf");
+
+ /* Other builtin functions we use. */
+ gfc_define_builtin ("__builtin_expect", ftype_expect,
+ BUILT_IN_EXPECT, "expect");
+ gfc_define_builtin ("__builtin_memcpy", ftype_memcpy,
+ BUILT_IN_MEMCPY, "memcpy");
}
+#undef DEFINE_MATH_BUILTIN
+
#include "gt-fortran-f95-lang.h"
#include "gtype-fortran.h"
diff -uNprxCVS clean/tree-ssa/gcc/fortran/mathbuiltins.def gcc/gcc/fortran/mathbuiltins.def
--- clean/tree-ssa/gcc/fortran/mathbuiltins.def 1970-01-01 01:00:00.000000000 +0100
+++ gcc/gcc/fortran/mathbuiltins.def 2003-08-30 17:21:06.000000000 +0100
@@ -0,0 +1,8 @@
+DEFINE_MATH_BUILTIN (ATAN, "atan", 1)
+DEFINE_MATH_BUILTIN (ATAN2, "atan2", 2)
+DEFINE_MATH_BUILTIN (COS, "cos", 1)
+DEFINE_MATH_BUILTIN (EXP, "exp", 1)
+DEFINE_MATH_BUILTIN (LOG, "log", 1)
+DEFINE_MATH_BUILTIN (SIN, "sin", 1)
+DEFINE_MATH_BUILTIN (SQRT, "sqrt", 1)
+DEFINE_MATH_BUILTIN (TAN, "tan", 1)
diff -uNprxCVS clean/tree-ssa/gcc/fortran/trans-intrinsic.c gcc/gcc/fortran/trans-intrinsic.c
--- clean/tree-ssa/gcc/fortran/trans-intrinsic.c 2003-08-22 23:46:18.000000000 +0100
+++ gcc/gcc/fortran/trans-intrinsic.c 2003-08-30 18:16:59.000000000 +0100
@@ -52,6 +52,8 @@ typedef struct gfc_intrinsic_map_t GTY((
garbage collection/gengtype parsing mechanism. */
const enum gfc_generic_isym_id id;
const char *name;
+ const int code4;
+ const int code8;
tree GTY(()) real4_decl;
tree GTY(()) real8_decl;
tree GTY(()) complex4_decl;
@@ -59,41 +61,28 @@ typedef struct gfc_intrinsic_map_t GTY((
}
gfc_intrinsic_map_t;
-#define I_LIB(id, name) {id, name, NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE},
+#define I_LIB(id, name) {GFC_ISYM_ ## id, name, \
+ END_BUILTINS, END_BUILTINS, \
+ NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE},
+#define DEFINE_MATH_BUILTIN(id, name, nargs) {GFC_ISYM_ ## id, name, \
+ BUILT_IN_ ## id ## F, BUILT_IN_ ## id, \
+ NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE},
static GTY(()) gfc_intrinsic_map_t gfc_intrinsic_map[] =
{
/* Math functions. These are in libm. */
- I_LIB (GFC_ISYM_SIN, "sin")
- I_LIB (GFC_ISYM_COS, "cos")
- I_LIB (GFC_ISYM_SQRT, "sqrt")
- I_LIB (GFC_ISYM_TAN, "tan")
- I_LIB (GFC_ISYM_ASIN, "asin")
- I_LIB (GFC_ISYM_ACOS, "acos")
- I_LIB (GFC_ISYM_ATAN, "atan")
- I_LIB (GFC_ISYM_ATAN2, "atan2")
- I_LIB (GFC_ISYM_SINH, "sinh")
- I_LIB (GFC_ISYM_COSH, "cosh")
- I_LIB (GFC_ISYM_TANH, "tanh")
- I_LIB (GFC_ISYM_EXP, "exp")
- I_LIB (GFC_ISYM_LOG, "log")
- I_LIB (GFC_ISYM_LOG10, "log10") I_LIB (GFC_ISYM_NONE, NULL)
-};
-#undef I_LIB
-
-typedef struct
-{
- const gfc_generic_isym_id id;
- const int code4;
- const int code8;
-}
-gfc_builtin_intrinsic_t;
+ I_LIB (ACOS, "acos")
+ I_LIB (ASIN, "asin")
+ I_LIB (COSH, "cosh")
+ I_LIB (LOG10, "log10")
+ I_LIB (SINH, "sinh")
+ I_LIB (TANH, "tanh")
+ /* Also the builtin math functions. */
+#include "mathbuiltins.def"
-static const gfc_builtin_intrinsic_t gfc_builtin_intrinsics[] = {
- {GFC_ISYM_SIN, BUILT_IN_SINF, BUILT_IN_SIN},
- {GFC_ISYM_COS, BUILT_IN_COSF, BUILT_IN_COS},
- {GFC_ISYM_SQRT, BUILT_IN_SQRTF, BUILT_IN_SQRT},
- {GFC_ISYM_NONE, 0, 0}
+ I_LIB (NONE, NULL)
};
+#undef I_LIB
+#undef I_BUILTIN
/* Evaluate the arguments to an intrinsic function. */
@@ -404,21 +393,15 @@ gfc_conv_intrinsic_conjg (gfc_se * se, g
void
gfc_build_intrinsic_lib_fndecls (void)
{
- const gfc_builtin_intrinsic_t *i;
gfc_intrinsic_map_t *m;
/* Add GCC builtin functions. */
- for (i = gfc_builtin_intrinsics; i->id != GFC_ISYM_NONE; i++)
+ for (m = gfc_intrinsic_map; m->id != GFC_ISYM_NONE; m++)
{
- for (m = gfc_intrinsic_map; m->id != GFC_ISYM_NONE; m++)
- {
- if (m->id == i->id)
- break;
- }
- assert (m->id != GFC_ISYM_NONE);
-
- m->real4_decl = built_in_decls[i->code4];
- m->real8_decl = built_in_decls[i->code8];
+ if (m->code4 != END_BUILTINS)
+ m->real4_decl = built_in_decls[m->code4];
+ if (m->code8 != END_BUILTINS)
+ m->real8_decl = built_in_decls[m->code8];
}
}
diff -uNprxCVS clean/tree-ssa/gcc/fortran/trans-types.c gcc/gcc/fortran/trans-types.c
--- clean/tree-ssa/gcc/fortran/trans-types.c 2003-08-21 23:41:42.000000000 +0100
+++ gcc/gcc/fortran/trans-types.c 2003-08-30 18:51:23.000000000 +0100
@@ -177,7 +177,6 @@ gfc_init_types (void)
TREE_TYPE (boolean_true_node) = boolean_type_node;
boolean_false_node = build_int_2 (0, 0);
TREE_TYPE (boolean_false_node) = boolean_type_node;
- signed_size_type_node = size_type_node;
}
/* Get a type node for an integer kind */