This is the mail archive of the fortran@gcc.gnu.org mailing list for the GNU Fortran 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: How to add intrinsic functions to gfortran?


On Friday 28 May 2004 20:08, Steve Kargl wrote:
> Is there a document that describes how to add an
> intrinsic function to gfortran?

No, but there's plenty of examples :)

> I've implemented G77's irand(), srand(), and rand()
> procedures.  srand() is an intrinsic subroutine and
> as far as I can tell it is seen, works, and is used by
> gfortran.  On the other hand, irand() and rand() are
> not working and I suspect some name mangling is need.

This is a good thing, however we need a way for the user to disable these 
additional intrinsics.

Actually the whole registering/checking/resolution of intrinsics needs a 
rewrite to make it easy to add and maintain new intrinsics.

Me and Steven Bosscher discussed this some time ago, and came up with ideas 
for autogenerating 90% of intrinsic.c, check.c and iresolve.c. I don't think 
we ever got any working code though.

> I'll restrict the discussion to irand() where the Fortran
> prototypes is
>
>    integer function irand(integer flag)
>
> In my C code, I have tried the following declarations
>
> GFC_INTEGER_4 prefix(irand) (GFC_INTEGER_4 flag)

You should use this one.

> GFC_INTEGER_4      __irand  (GFC_INTEGER_4 flag)
> GFC_INTEGER_4       _irand  (GFC_INTEGER_4 flag)
> GFC_INTEGER_4        irand  (GFC_INTEGER_4 flag)
>
> In all cases, gfortran compiles
>
>    program cc
>    integer i
>    i = irand(0)
>    end program cc
>
> to the following tree
>
> troutmask:sgk[286] more cc.f90.t03.original
>    MAIN__ ()
>    {
>      int4 i;
>
>      i = 0;
>    }

The frontend is replacing the intrinsic with the "known" value (see below).

> In intrinsic.c, I have
>
>   add_sym_1 ("irand", 0, 1, BT_INTEGER, di,
> 	     gfc_check_irand, gfc_simplify_irand, NULL,
> 	     i, BT_INTEGER, di, 0);
>
>   make_generic ("irand", GFC_ISYM_IRAND);
>
> where GFC_ISYM_IRAND is added to "enum gfc_generic_isym_id" in
> gfortran.h.   gfc_simplify_irand is required or gfortran yields
> an ICE.  It looks like
>
>    gfc_expr *
>    gfc_simplify_irand (gfc_expr * e)
>    {
>      gfc_expr *result;
>
>      if (e->expr_type != EXPR_CONSTANT) return NULL;
>
>      result = gfc_constant_result (BT_INTEGER, gfc_default_integer_kind(),
>        &e->where);
>
>      mpz_set (result->value.integer, e->value.integer);
>
>      return range_check (result, "IRAND");
>    }

The simplify functions basically perform constant folding. The above routine 
effectively says that the function will return its argument unmodified, and 
makes the substitution if the value if known at compile time.

I'd guess that irand doesn't need/want a simplify function.

> I've tried various version of a gfc_resolve_irand function to
> set the function name to each of the above 4 prototype function
> names without much luck.

I assume you modified the call to add_sym_1 so it was actually used ;)

> Any hints would be appreciated.

The code generation for intrinsic functions is in trans-intrinsic.c. The best 
starting point is probably gfc_conv_intrinsic_function.

a) Generate inline code, possibly including calls to helper functions. In this 
case this probably means the libc rand() and srand() functions.
The resolved name is usually ignored, although you may still need the 
resolution function.

b) let it drop through to gfc_conv_intrinsic_funcall (Like MATMUL and 
DOT_PRODUCT). This uses the resolved name, and it will be called exactly like 
and external function.

Note that gfc_is_intrinsic_libcall is only for functions that return arrays 
(as the comment says), and gfc_conv_intrinsic_lib_function contains magic you 
almost certainly don't want.

HTH

Paul


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