Subject: hpff-doc: Interoperability with C

From: <[email-masked]> (Henry Zongaro)
Date: Tue, 6 Aug 1996 09:11:36 -0400 (EDT)

---------------------------------------------------------------------------
[email-masked] is a mailing list for HPF 2.0 language specification
authors and editors.  Instructions for adding or deleting yourself from this
list appear at the bottom of this message.
---------------------------------------------------------------------------
Hello,

     Here's the latest draft of the Interoperability with C stuff.  I wasn't
sure how much of the MAP_TO would be described here and how much would be
described in the general section on extrinsic interfaces; I kept the syntax of
MAP_TO, but dropped the syntax for EXTERNAL_NAME.  There are still many
references to EXTRINSIC(C), which is no longer the correct name.

     I've also had a request from Michael Hennecke to split the sub-specifiers
of MAP_TO into separate specifiers - so rather than specifying something like:

        INTEGER, MAP_TO(TYPE='int', PASSBY='ref', LAYOUT='c_array') :: I(10)

we'd have

        INTEGER, MAP_TO('int'), PASSBY('ref'), LAYOUT('c_array') :: I(10)

but that's not been incorporated.  I'll describe it at the next meeting.

     Please check the notes to reviewers for some of the unresolved issues.

Thanks,

Henry

%%% Start temporary stuff

\newenvironment{reviewers}{\begin{list}{}{}\item[]{\it Note
        to reviewers.}
}{{\rm ({\it End of note to reviewers.})} \end{list}}

%%% End temporary stuff

% interop.tex

% Initial Version of June 21, 1996
% Andy Meltzer and Henry Zongaro
% Version 0.1 - July 11, 1996
% Version 0.2 - August 2, 1996

\chapter{Approved Extension for HPF Interoperability with C}
\label{ch-interop}

{\em
Comments on this chapter should be directed to Henry Zongaro
({\tt [email-masked]}), Andy Meltzer ({\tt [email-masked]}) and
{\tt [email-masked]}.
Please use ``{\tt Comments on Interoperability}'' as the {\tt Subject:}
line.
\par
}

A common problem faced by Fortran users is the need to call procedures
written in other languages, particularly those writen in C or which have
interfaces that can be described by C prototypes.  Although many Fortran
implementations provide methods which solve this problem, these solutions are
rarely portable.

This section defines a method of specifying interfaces to procedures defined
in C that removes most of the common obstacles to interoperability, while
retaining portability.

\section{Specification of Interfaces to Procedures Defined in C}

\begin{reviewers}
This section needs to be harmonized with the recent changes to the
{\tt EXTRINSIC} attribute.
\end{reviewers}
If a user wishes to specify that a procedure is defined by a C procedure,
this is specified with an {\it extrinsic-kind-keyword} of {\tt C}, as specified
in Section ??.

% \BNF
% function-stuff    \IS  ( [ dummy-arg-name-list ] ) [ postfix ]
%
% subroutine-stuff  \IS  [ ( [ dummy-arg-list ] ) ] [ postfix ]
%
% postfix           \IS  postfix-spec [ postfix-spec ] ...
%
% postfix-spec      \IS  RESULT ( result-name )
%                   \OR  EXTERNAL_NAME ( char-literal-constant )
% \FNB

\begin{constraints}

% \item  A {\it postfix} shall contain no more than one of each type of
%       {\it postfix-spec}.
%
% \item  {\tt RESULT} shall not be specified as part of a {\it subroutine-stmt}.
%
% \item  {\tt EXTERNAL_NAME} shall only be specified as part of a
%        {\it subroutine-stmt} or {\it function-stmt} for which a
%        {\it prefix-spec} of {\tt EXTRINSIC(C)} has been specified.

\item  A function for which a {\it prefix-spec} of {\tt EXTRINSIC(C)} has
       been specified shall have a scalar result of type integer, real or
       double precision real.

\item  A dummy argument of a procedure for which a {\it prefix-spec} of
       {\tt EXTRINSIC(C)} has been specified shall not be an assumed-shape
       array, shall not have the {\tt POINTER} attribute, shall not have the
       {\tt TARGET} attribute, nor shall it have a subobject which has the
       {\tt POINTER} attribute.

\item  The bounds of a dummy argument of a procedure for which a
       {\it prefix-spec} of {\tt EXTRINSIC(C)} has been specified shall not
       be specified by specification expressions which are not constant
       specification expressions, nor shall the character length parameter
       of a dummy argument of such a procedure be specified by a specification
       expression which is not a constant specification expression.

\item  A {\it dummy-arg-list} of a subroutine which has an
       {\it extrinsic-kind-keyword} of {\tt C} shall not have a {\it dummy-arg}
       which is {\tt *} or a dummy procedure.
\end{constraints}

The value of the {\it char-literal-constant} in the {\tt EXTERNAL_NAME}
specifier gives the name of the procedure as defined in C.  This value need
not be the same as the procedure name specified by the {\it function-stmt}
or {\it subroutine-stmt}.  If {\tt EXTERNAL_NAME} is not specified, it is
as if it was specified with a value which is the same as the procedure name
in lower case letters.

% \begin{reviewers}
% Should we force user to specify {\tt EXTERNAL_NAME}?  If not, should the
% folding be to lower case or upper?  Although lower case folding is common in
% UNIX environments, is it common elsewhere?
% \end{reviewers}

% Syntax rule H6?? is rewritten here:
% \BNF
% extrinsic-kind-keyword  \IS  HPF
%                         \OR  HPF_LOCAL
%                         \OR  HPF_SERIAL
%                         \OR  C
% \FNB

%\begin{constraints}

% \item  An {\it extrinsic-kind-keyword} of {\tt C} shall only be specified
%        as part of the {\it function-stmt} or {\it subroutine-stmt} of a
%        procedure that is declared to be a procedure by an interface body.
%
%\end{constraints}

The {\tt EXTRINSIC(C)} {\it prefix-spec} helps a compiler identify a procedure
that is defined in C, so that it can take appropriate steps to ensure that
the procedure is invoked in the manner required by the C compiler.

\begin{implementors}
A vendor may feel compelled to provide support for more than one C compiler,
if different C compilers available for a system provide different procedure
calling conventions or different data type sizes.  For instance, a vendor's
compiler may provide support for an {\tt EXTRINSIC(GNU_C)} {\it prefix-spec},
or it may provide support through the use of compiler switches.
\end{implementors}

\section{Specification of Data Type Mappings}

The {\tt MAPTO} attribute is the principle new feature which facilitates
referencing procedures defined in C from within Fortran programs.  It allows
the user to specify conversions required to associate the actual arguments
specified on the procedure reference with the formal arguments defined by
the referenced procedure.  The attribute has several optional specifiers.  The
TYPE= specifier indicates the type of the C data to which the HPF data shall
be converted by the compiler; the PASSBY= specifier indicates whether a C
pointer to the dummy argument needs to be passed; the LAYOUT= specifier
indicates for an array whether the array element order needs to be changed from
Fortran's array element ordering to C's.

\BNF
attr-spec  \IS  MAPTO ( [ TYPE= ] mapto-type-spec
                        [ , [ PASSBY= ] passby-spec ]
                        [ , [ LAYOUT= ] layout-spec ] )

mapto-type-spec \IS  default-char-literal-constant

% mapto-type-spec \IS  INT
%           \OR  LONG
%           \OR  SHORT
%           \OR  CHAR
%           \OR  FLOAT
%           \OR  DOUBLE
%           \OR  LONG_DOUBLE
%           \OR  CHAR_PTR
%           \OR  struct-mapto

% struct-mapto  \IS  ( mapto-type-spec-list )

layout-spec   \IS  default-char-literal-constant

passby-spec \IS  default-char-literal-constant
\FNB

\begin{constraints}

\item  The {\tt MAPTO} attribute shall only be specified for a dummy argument
       or function result variable of a function or subroutine which has an
       {\it extrinsic-kind-keyword} of {\tt C}.  In addition, the {\tt MAPTO}
       attribute shall be specified for all such dummy arguments and function
       result variables.

\item  If the {\tt MAPTO} attribute is specified for a variable, the
       {\it mapto-type-spec} specified shall be compatible with the type of the
       variable.

\item  The {\it layout-spec} specifier of the {\tt MAPTO} attribute shall only
       be specified for a dummy argument which is an array.

\item  A {\it layout-spec} shall not be specified for an assumed-size array.
\end{constraints}

If the compiler is capable of representing letters in both upper and lower
case, the value specified for a {\it mapto-type-spec}, {\it layout-spec}
or {\it passby-spec} is without regard to case.  Any blanks specified for a
{\it mapto-type-spec}, {\it layout-spec} or {\it passby-spec} shall be ignored
by the compiler for the purposes of determining its value.

\begin{reviewers}
I don't believe the following definition of {\tt C_VOID_POINTER} is going to
work.  This can get us to {\tt void *}, but what about {\tt int *},
{\tt float *}, etc. that might appear within {\tt struct} definitions?  Or
do we turn a blind eye and not support them?
\end{reviewers}

An implementation shall provide a module, {\tt ISO_C}, which shall define a
derived type, {\tt C_VOID_POINTER}.  The components of the {\tt C_VOID_POINTER}
type shall be private.

\begin{users}
The {\tt C_VOID_POINTER} type provides a method of using {\tt void *}
pointers in a program, but does not give the user any way of manipulating
such a pointer in the Fortran part of the program, since I/O cannot be
performed on an object with private components outside the module which defines
the type, neither can the components or structure constructor of such a
structure be used outside of the module which defines the type.
\end{users}

\begin{reviewers}
I will be the first to admit that the following on mapped to types is very
difficult to read.  Any suggestions for improvement will be happily
entertained.
\end{reviewers}

The values permitted for a {\it mapto-type-spec} are {\tt INT}, {\tt LONG},
{\tt SHORT}, {\tt CHAR}, {\tt FLOAT}, {\tt DOUBLE}, {\tt LONG_DOUBLE},
{\tt CHAR_PTR}, {\tt VOID_PTR}
or a comma-separated list, delimited by parentheses, of values
which are permitted for a {\it mapto-type-spec}.

A {\it mapto-type-spec} whose value is {\tt INT}, {\tt LONG}, {\tt SHORT}
or {\tt CHAR} is
compatible with the intrinsic type integer.  A {\it mapto-type-spec} whose
value is
{\tt FLOAT}, {\tt DOUBLE} or {\tt LONG_DOUBLE} is compatible with the intrinsic
type real.
A {\it mapto-type-spec} whose value is {\tt CHAR_PTR} is compatible with the
intrinsic type
character.  A {\it mapto-type-spec} whose value is {\tt VOID_PTR} is compatible
with the derived type {\tt C_VOID_POINTER} defined by the module {\tt ISO_C}.
A {\it mapto-type-spec} which is a parenthesised list of values is
compatible with a derived type if each value in the list
is compatible with the corresponding components of the
derived type.

The values permitted for a {\it passby-spec} are {\tt VAL}, {\tt REF},
{\tt RREF}, {\tt RRREF} or {\tt RRRREF}.  If the {\it passby-spec}
is not specified, the value {\tt VAL} is assumed.  If a {\it passby-spec} of
{\tt VAL} is specified, the dummy argument shall not have the
{\tt INTENT(OUT)} or {\tt INTENT(INOUT)} attribute specified.  If a value of
{\tt REF}, {\tt RREF}, {\tt RRREF} or {\tt RRRREF} is specified for the
{\it passby-spec}, an associated actual argument shall be a variable.

The value of the {\it mapto-type-spec} specified for a dummy argument in
the interface body of a procedure with the {\tt EXTRINSIC(C)}
{\it prefix-spec} shall be such that at
least one of the permitted mapped to types is the same as
the C data type of the corresponding formal argument in the C
definition of the procedure (or a type that is equivalent to one of the
permitted mapped to types).
The C data type of a function in the C
definition of a procedure shall be one of the permitted mapped to types
(or a type that is equivalent to the permitted mapped to types) specified
for the function result variable specified in the interface body of a
function with the {\tt EXTRINSIC(C)} {\it prefix-spec}.
  If a subroutine has
been specified with a {\it prefix-spec} of {\tt EXTRINSIC(C)}, the C definition
of the procedure shall be specified with a data type of {\tt void}.

\begin{reviewers}
I'm not sure how the C standard describes types that are "equivalent".  Anyone
know the correct terminology?
\end{reviewers}

The permitted mapped to types of a scalar variable of intrinsic type,
when the value specified for the {\tt PASSBY} keyword is {\tt VAL}:
\begin{itemize}
\item  is {\tt int} if a {\it mapto-type-spec} of {\tt INT} is specified for the
       variable;
\item  is {\tt long} if a {\it mapto-type-spec} of {\tt LONG} is specified
       for the variable;
\item  is {\tt short} if a {\it mapto-type-spec} of {\tt SHORT} is specified
       for the variable;
\item  is {\tt char} if a {\it mapto-type-spec} of {\tt CHAR} is specified
       for the variable;
\item  is {\tt float} if a {\it mapto-type-spec} of {\tt FLOAT} is specified
       for the variable;
\item  is {\tt double} if a {\it mapto-type-spec} of {\tt DOUBLE} is specified
       for the variable;
\item  is {\tt long double} if a {\it mapto-type-spec} of {\tt LONG_DOUBLE}
       is specified for the variable; or
\item  are {\tt char *} if a {\it mapto-type-spec} of {\tt CHAR_PTR} is
       specified for the variable.
\item  is {\tt void *} if a {\it mapto-type-spec} of {\tt VOID_PTR}
\end{itemize}

The permitted mapped to types of an array are the same as the permitted mapped
to types of a scalar variable of that type followed by a left bracket
({\tt [}),
followed by the extent of the corresponding dimension of the dummy argument,
following by a right bracket ({\tt ]}), for each dimension of the array.  If
no value is specified for the {\tt LAYOUT=} specifier, the corresponding
dimensions of the dummy argument are determined from right to left; if the
value C_ARRAY is specified for the {\tt LAYOUT=} specifier, the corresponding
dimensions of the dummy argument are determined from left to right.

The permitted mapped to types of a scalar variable of derived type are the
structures whose members are of one of the permitted mapped to types of the
components of the derived type.

The permitted mapped to types of a dummy argument, when the value specified
for the {\tt PASSBY} keyword is {\tt REF}, {\tt RREF}, {\tt RRREF} or
{\tt RRRREF}, are the same as the permitted mapped to types of such a dummy
argument when the {\tt PASSBY} keyword is {\tt VAL}, except that for {\tt REF}
the permitted mapped to types have a single {\tt *} (asterisk) appended,
for {\tt RREF} two asterisks are appended, for {\tt RRREF} three asterisks are
appended, and for {\tt RRRREF} four asterisks are appended.

\begin{reviewers}
There was some feeling at the May meeting that permitting {\tt RREF}
to help map to pointers to pointers wasn't really beneficial.  Mainly, it
was felt that people use things like {\tt int **p} when they want to return
(or modify) a pointer to a buffer area, and that there would be no way of
accessing something like that on the Fortran side via the {\tt RREF}.

Opinions?
\end{reviewers}

If there is a mismatch between the precision, representation method, range of
permitted values or storage sequence between the type of the dummy argument and
the permitted mapped to type of the dummy argument, the compiler shall ensure
that, for the duration of the reference to a procedure defined with an
{\it extrinsic-kind-keyword} of {\tt C}, the dummy argument is represented in
a manner that is compatible with the expectations of the C processor for an
object of the permitted mapped to type.  Upon return from the procedure, the
compiler shall ensure that the value of an actual argument which is a variable
is restored to the specified type and kind.

\begin{users}
This rule was created to ensure the portability of interoperability.  However,
it should be noted that for large objects, a significant overhead may be
incurred if there is a mismatch between the representation method used for
the data type versus the representation method used for the permitted mapped to
type.
\end{users}

\begin{users}
In some cases, this may cause the value of the actual argument to change
without the value being modified by the procedure referenced.  For example,

\CODE
      PROGRAM P
        INTERFACE
          EXTRINSIC(C) SUBROUTINE C_SUB(R)
            REAL(KIND(1.0D0)), MAPTO('FLOAT', 'REF') :: R
          END SUBROUTINE C_SUB
        END INTERFACE
        REAL(KIND(0.0D0))

        R = 1.0D0 + 1.0D-10
        PRINT *, R
        CALL C_SUB(R)
        PRINT *, R
      END PROGRAM P

      void c_sub(float *r)
      {
      }
\EDOC

Might print

\CODE
 1.00000000050000004
 1.00000000000000000
\EDOC

although the value of {\tt *r} is not modified in {\tt c_sub}.
\end{users}

If the range of permitted values of the type and mapped to type differ and
the value of the actual argument or some subobject of the actual argument is
not within the permitted range of the mapped to type, the value of the
associated dummy argument or subobject becomes undefined.  Conversely, if
the value of the dummy argument or some subobject of the dummy is not within
the permitted range of values of the associated dummy argument, and the
associated actual argument is a variable, the value of the associated actual
argument or subobject of the actual becomes undefined.

The value permitted for a {\it layout-spec} is {\tt C_ARRAY}.

If no {\it layout-spec} is specified for a dummy array argument, the array
element order shall be the same as that specified by Fortran.  If the value of
{\it layout-spec} specified is {\tt C_ARRAY}, the array element order of the
array shall be transposed for the duration of the reference to the procedure.

\begin{reviewers}
Note that we have no way of specifying {\it layout-spec} for structure
components.
\end{reviewers}

\subsection{Examples of Data Type Mappings}

Some examples should help to clarify what sorts of C procedure definitions
would be permitted given an interface body in a Fortran program.  For example,
the following interface body

\CODE
        INTERFACE
          EXTRINSIC('C') SUBROUTINE C_SUB(I, R, DARR, STRUCT)
            INTEGER, MAPTO('INT') :: I
            REAL, MAPTO('FLOAT', PASSBY='REF') :: R
            REAL(KIND(1.0D0)), MAPTO('DOUBLE') :: DARR(10)
            TYPE DT
              SEQEUNCE
              INTEGER :: I, J
            END TYPE DT
            TYPE(DT), MAPTO('(INT, LONG)', 'REF') :: STRUCT
          END SUBROUTINE C_SUB
        END INTERFACE
\EDOC

could correspond to a C procedure which has the prototype

\CODE
        void c_sub(int i, float r*, double darr[10], struct {int i, long j} *)
\EDOC

In the following example of the {\it layout-spec},

\CODE
      PROGRAM P
        INTERFACE
          EXTRINSIC('C') SUBROUTINE C_SUB(A, B)
            INTEGER, MAPTO('INT') :: A(2,2)
            INTEGER, MAPTO('INT', LAYOUT='C_ARRAY') :: B(2,2)
          END SUBROUTINE C_SUB
        END INTERFACE

        INTEGER :: AA(2,2), BB(2,2)
        CALL C_SUB(AA, BB)
      END PROGRAM P

      void c_sub(int a[2][2], b[2][2])
\EDOC

the correspondence between elements of {\tt AA} and {\tt a}, and elements of
{\tt BB} and {\tt b} is

\CODE
        AA(1,1)   a[0][0]              BB(1,1)   b[0][0]
        AA(2,1)   a[0][1]              BB(2,1)   b[1][0]
        AA(1,2)   a[1][0]              BB(1,2)   b[0][1]
        AA(2,2)   a[1][1]              BB(2,2)   b[1][1]
\EDOC

\end{document}
---------------------------------------------------------------------------
To (un)subscribe to this list, send mail to [email-masked].
Leave the subject line blank, and in the body put the line
(un)subscribe <email-address>
---------------------------------------------------------------------------