Avoiding gather and scatter when calling Fortran 77 code from Fortran 90 code6647546Abstract In accordance with methods and systems consistent with the present invention, a system that automatically generates Fortran 90 interfaces to Fortran 77 code is provided. These interfaces provide for the use of optional parameters and, because they are written in Fortran 90, also allow for parameter checking. These interfaces are automatically generated to allow a programmer to reap the benefits of Fortran 90 calling without having to rewrite the Fortran 77 underlying code. When generating the interfaces, the method performs an optimization that saves a significant amount of processing time as well as a significant amount of memory. This optimization involves generating the interfaces in such a way as to prevent the compiler from performing a gather and a scatter. Claims What is claimed is: Description FIELD OF THE INVENTION
TABLE 1
INTERFACE Interface_Name
{SUBROUTINE .vertline. TYPE FUNCTION} (Parameter1,
[Parameter2, . . . , ParameterN])
TYPE Paramete4
TYPE Parameter2
. . .
TYPE ParameterN
END SUBROUTINE
END INTERFACE
Following is an example of an F77 Interface for the CAXPY Fortran 77 subprogram, which performs the addition of two vectors X and Y and adds a constant Alpha:
TABLE 2
INTERFACE CAXPY
SUBROUTNE CAXPY (N, ALPHA, X, INCX, Y, INCY)
INTEGER : : N
COMPLEX : : ALPHA
COMPLEX : : X (*)
INTEGER : : INCX
COMPLEX : : Y (*)
INTEGER : : INCY
END SUBROUTINE
END INTERFACE
An example of an F90 stub routine for the CAXPY subprogram follows:
TABLE 3
SUBROUTINE CAXPY_2 (N, ALPHA, X, Y)
IMPLICIT NONE
INTEGER : : N
COMPLEX : : ALPHA
COMPLEX, DIMENSION (:) : : X
INTEGER : : INCX
COMPLEX, DIMENSION (:) : : Y
INTEGER : : INCY
INCX=(LOC(X(2)) - LOC(X(1))) / 8
INCY=(LOC(Y(2)) - LOC(Y(1))) / 8
CALL CAXPY (N, ALPHA, %val (loc (X)), INCX, %VAL (loc (Y),
INCY)
RETURN
END
In the stub, CAXPY_2, the two integer stride parameters (INCX and INCY) are not passed into the subprogram, so the stub routine assigns values for them before passing the fully specified parameter list to the F77 subprogram CAXPY. For example, the value of INCX is calculated by analyzing the difference in the address between successive elements in the X array, and the stub performs a similar calculation to assign the value of INCY. FIG. 3 depicts a flowchart of the steps performed by methods and systems consistent with the present invention when creating the stubs. The first step performed is to generate the F77 interface file from the F77 code by invoking the interface generator (step 302). In this step, the interface generator scans the F77 source code and creates an interface file for each subprogram contained in it according to the definition provided above. The interface generator then adds code-generator statements to the interface file to facilitate the stub generator in creating stubs for each subprogram. It parses the arguments of each subprogram and adds a comment line that provides meaningful information so that the stub generator can generate a stub. For example, such meaningful information may include how to generate a value for a given parameter if the value for the parameter is missing. After invoking the interface generator, the user invokes the stub generator (step 304). The stub generator reads the interface files and generates stub routines by using the code-generator statements. The stub generator also produces interfaces for the stub routines. These interfaces are used to resolve references during compilation of the F90 program. Once generated, the stubs are compiled and can be linked into the F90 source code to enable their invocation from the F90 source code (step 306). FIGS. 4A, 4B, and 4C depict a flowchart of the steps performed by the interface generator. The first step performed by the interface generator is to select a subprogram from the F77 code (step 402). Next, the interface generator creates an interface file for this subprogram (step 404). In this step, the interface generator generates a definition for the subprogram similar to that described above with respect to Table 1. After creating the file, the interface generator determines whether there are more subprograms in the F77 code (step 406). If so, processing continues to step 402. Otherwise, the interface generator performs a second pass through the F77 code by selecting a subprogram and its corresponding interface file (step 408). Next, the interface generator determines if more than 32 stubs could be generated by determining the various legal combinations of parameters (step 409). A "legal" combination is one in which the specified parameters can uniquely identify a stub routine and the values of the missing parameters can be calculated. If more than 32 stubs could be generated, the interface generator provides an indication to the user (step 410), so that after the interface generator completes its processing, the user has the option of editing the stubs to remove a number of them that will most likely not be used. After providing the indication to the user or if there are 32 or less stub routines to be generated, the interface generator inserts "G" code-generator statements into the interface file indicating the stub routines that should be generated, one for each legal combination of parameters (step 412). The "G" code-generator statement takes the form of G(list), where "list" specifies a valid parameter list. An example of the "G" code-generator statements inserted into an interface file follows:
TABLE 4
!#G (N, X, INCX, Y, INCY)
!#G (X,Y)
INTERFACE AG
SUBROUTINE RAG (N, X, INCX, Y, INCY)
INTEGER : : N !#D (100)
REAL : : X (:)
INTEGER : : INCX !#D(1)
REAL : : Y (:)
INTEGER : : INCY !#D(1)
END SUBROUTINE
END INTERFACE
Next, the interface generator identifies the family in which this subprogram operates (step 414). An implementation of methods and systems consistent with the present invention operates on a library of subprograms that perform scientific calculations. This library groups the subprograms into families, and in this step, the interface generator identifies the generic family that the subprogram is associated with by determining the root of the subprogram name. In accordance with methods and systems consistent with the present invention, the first two characters of the subprogram name indicate both the input and output types with the generic family name following. If the family name cannot be identified in this manner, then the programmer has specified the family name in the comments of the source code and the interface generator identifies the family name from this information. After identifying the generic family name, the interface generator inserts a GENERIC code-generator statement next to the subprogram name indicating the generic family name. The GENERIC code-generator statement takes the form of GENERIC(name), where the "name" refers to the family name. An example of the GENERIC code-generator statement follows:
TABLE 5
INTERFACE ICAMAX !#GENERIC (IAMAX)
SUBROUTINE ICAMAX (N, X, INCX)
INTEGER : : N !#D (100)
COMPLEX : : X (:)
INTEGER : : INCX
END INTERFACE
After identifying the family, the interface generator selects a parameter within the subprogram (step 416). The arguments for the subprograms in the F77 code contain comments that provide a significant amount of information about that parameter, such as whether the parameter is an input, output, or input/output parameter; its type; and the meaning associated with its values. In accordance with methods and systems consistent with the present invention, the parameter descriptions closely conform to the following form:
TABLE 6
Parameter
Name Comment Line in Source Code
N (input) INTEGER
The order of the matrix A. N>=0.
D (input/output) COMPLEX array, dimension (N)
On entry, the diagonal elements of A.
On exit, the diagonal elements DD.
L (input/output) COMPLEX array, dimension (N-1)
On entry, the subdiagonal elements of A.
On exit, the subdiagonal elements of LL and DD.
SUBL (output) COMPLEX array, dimension (N-2)
On exit, the second subdiagonal elements of LL.
NRHS (input) INTEGER
The number of right hand sides, i.e., the number of columns
of matrix B. NRHS>=0.
B (input/output) COMPLEX array, dimension (LDB, NRHS)
On entry, the N-by-NRHS right hand side matrix B.
On exit, if INFO=0, the N-by-NRHS solution matrix X.
LDB (input) INTEGER
The leading dimension of the array B. LDB>=max (1, N).
IPIV (input) INTEGER array, dimension (N)
Details of the interchanges and block pivot. If IPIV (K) >
0, 1 by 1 pivot, and IPIV (K) = K + 1 an interchange done;
If IPIV (K) < 0, 2 by 2 pivot, no interchange required.
INFO (output) INTEGER
= 0: successful exit
<0: if INFO = -k, the k-th argument had an illegal value
>0: if INFO = k, D (k) is exactly zero. The factorization
has been completed, but the block diagonal matrix DD
(that is D (K)) is exactly singular, and division by zero
will occur if it is used to solve a system of equations.
Thus, when an argument "N" appears in a subprogram, its associated comment indicates that it is an input parameter, it is of type integer, and its purpose is to define the order of the matrix A. After selecting a parameter, the interface generator determines whether the value of this parameter can be calculated from either the other parameters or another source (step 418). For example, if the selected parameter were a length parameter or a stride parameter, the value of the parameter can be obtained through a system call to Fortran 90 to identify the size or stride of the parameter. If the value of the parameter is calculatable, the interface generator inserts a code-generator statement "D" as a comment next to the parameter declaration (step 420). The "D" code-generator statement indicates that the parameter is optional because its value can be derived from another source. The "D" code-generator statement takes the form of D(expression), where "expression" indicates how to derive the value of the parameter. A valid "expression" could include any constant term, any expression which may include constant terms and/or actual parameters, or other code-generator statements. An example of the "D" code-generator statement follows:
TABLE 7
INTERFACE AD
SUBROUTINE CAD (N, X)
INTEGER : : N !#D (100)
COMPLEX : : X (:)
END SUBROUTINE
END INTERFACE
INTERFACE AD
SUBROUTINE CAD (N, X, M)
INTEGER : : N !#D (#SIZE (X))
COMPLEX : : X (*)
INTEGER : : M !#D (N)
END SUBROUTINE
END INTERFACE
The interface generator then determines if error checking was requested for this argument (step 422 in FIG. 4B). This determination is made by examining the comments associated with the parameter. If error checking was requested by the programmer, an indication would be provided in the comments, and in this case, the interface generator inserts the HERE code-generator statement (step 424). The HERE code-generator statement checks to ensure that the value for the associated parameter is supplied when a given expression evaluates to true. If the value is not provided, an error will be printed and execution will stop. The HERE code-generator statement takes the form of HERE(expression), where "expression" evaluates to true or false. An example follows:
TABLE 8
INTERFACE CHERE
SUBROUTINE CHERE (FLAG, N, X, XOPT)
CHARACTER : : FLAG !#D (`Y`)
INTEGER: : : N !#D (#SIZE (X))
COMPLEX : : X (*)
COMPLEX : : XOPT (*) !#HERE(FLAG .EQ. `Y`)
END SUBROUTINE
END INTERFACE
Next, the interface generator determines if the argument has a conditional value (step 426). If so, the interface generator inserts the IF code-generator statement (step 428). In this step, the programmer has indicated in the source code the conditional requirement, and thus, the interface generator inserts an appropriate expression indicating the conditionality of the argument. The "IF" code-generator statement is defined as IF(expression, default1{ELSE default2}), where if "expression" evaluates to true, then the value of this argument is default1. Otherwise, the value is default2.
TABLE 9
INTERFACE IF
SUBROUTINE CIF (FLAG1, N, ARRAY)
CHARACTER : : FLAG1 !#D (`Y`)
INTEGER : : N !#IF ((FLAG1 .EQ. `Y`), #D (100),
#ELSE (#D (200))
INTEGER : : ARRAY (:)
END SUBROUTINE
END INTERFACE
After inserting the IF code-generator statement or if the argument does not have a conditional value, the interface generator determines if this argument has a return value (step 430). If so, the interface generator inserts the INFO code-generator statement (step 432). This determination is made by identifying whether the word "status" appears in the comments. If such a comment appears, then the INFO code-generator statement is added which checks the value against an expected value per the comment, and if it is not correct, it generates an error. The INFO code-generator statement is defined as INFO{(ok_expression)}, where "ok_expression" resolves to the expected value. The INFO argument is an argument that returns the status of the call. If the caller supplies this argument, then the stub passes it into the F77 subprogram and does no further processing. If the caller does not supply it, then the stub creates a variable of the correct type and passes it to the F77 subprogram. If ok expression is not supplied, the stub assumes that INFO.EQ.0 indicates a proper return. If ok_expression is supplied as a scalar, the stub assumes that INFO.EQ.ok_expression indicates a proper return. If ok_expression is supplied as an expression, the stub evaluates that expression exactly as it appears. A result of .TRUE indicates a proper return, and any other result indicates an improper return or error condition in the called subprogram. An example of the INFO code-generator statement follows:
TABLE 10
INTERFACE INFO
SUBROUTINE SINFO (N, INFO)
INTEGER : : N !#D (100)
INTEGER : : INFO !#INFO
END SUBROUTINE
END INTERFACE
Next, the interface generator inserts the directionality of the parameter into the interface file (step 434). In this step, the interface generator determines if the parameter is an in/out, input, or output parameter by examining the comments in the source code. After making this determination, either an input/output, input, or output code-generator statement is inserted into the interface file. If the parameter is an input/output parameter, it is passed with input and output semantics, as required by the language. In the case of C interfaces, this means that the C interface passes a scalar parameter by reference. This parameter allows the compiler to perform optimizations across subprogram boundaries. An example of the INOUT code-generator statement follows:
TABLE 11
INTERFACE INOUT
SUBROUTINE SINOUT (N, A, RECOND)
INTEGER : : N !#D (#SIZE (A))
INTEGER : : A(*)
REAL : : RCOND !#INOUT
END SUBROUTINE
END INTERFACE
If the parameter is an INPUT parameter, it is passed with input semantics. In the case of C interfaces, this means that the C interface can pass the parameter by value. This parameter allows the compiler to perform optimizations across subprogram boundaries.
TABLE 12
INTERFACE INPUT
SUBROUTINE SINPUT (N, A, RECOND)
INTEGER : : N !#D (#SIZE (A))
INTEGER : : A(*)
REAL : : RCOND !#INPUT
END SUBROUTINE
END INTERFACE
If the parameter is an OUTPUT parameter, it is passed with output semantics. In the case of C interfaces, this means that the C interface needs to pass a scalar parameter by reference. This parameter allows the compiler to perform optimizations across subprogram boundaries.
TABLE 13
INTERFACE OUTPUT
SUBROUTINE SOUTPUT (N, A, RECOND)
INTEGER : : N !#D (#SIZE (A))
INTEGER : : A(*)
REAL : : RCOND !#OUTPUT
END SUBROUTINE
END INTERFACE
After inserting the directionality, the interface generator determines if the argument will return a multi-dimensional variable (step 436). If so, it inserts a RANK code-generator statement indicating that this stub should generate both a multi-dimensional array as well as a single dimensional variable in the event that the programmer was only expecting a one-dimensional variable (step 438). The RANK code-generator statement is defined as RANK(list), where list indicates the possible dimensions of the parameter. An example follows:
TABLE 14
INTERFACE RANK
SUBROUTINE CRANK (N, ARRAY)
INTEGER : : N
COMPLEX : : ARRAY (:,:) !#RANK (1)
END SUBROUTINE
END INTERFACE
Next, the interface generator determines if the size of the argument is declared in terms of another argument (step 438 in FIG. 4C), and if so, it adds the SIZE code-generator statement (step 440). The SIZE code-generator statement is defined as SIZE(name, [#DIM=d]), where "name" is the name of the variable that this parameter acts as the size of and "DIM" indicates the dimensionality of the variable. Following is an example of the SIZE code-generator statement:
TABLE 15
INTERFACE SIZE
SUBROUTINE DSIZE (N, ARRAY)
INTEGER : : N !#D (#SIZE (ARRAY))
DOUBLE PRECISION : : ARRAY (:)
END SUBROUTINE
END INTERFACE
The interface generator then determines if this parameter is a stride parameter indicating the stride of another parameter by examining the comments associated with the parameter (step 442). If the comments indicate that this parameter is a stride for another parameter, the interface generator inserts the stride code-generator statement (step 444). The STRIDE code-generator statement is defined as STRIDE(name,[#DIM=d]), where "name" indicates the parameter that this parameter is the stride for and "DIM" indicates the dimensionality of the parameter.
TABLE 16
INTERFACE INPUT
SUBROUTINE CSTRIDE (N, X, INCX, Y, INCY)
INTEGER : : N !#D (#SIZE (X))
COMPLEX : : X
INTEGER : : INCX !#D (#STRIDE (X))
COMPLEX : : Y
INTEGER : : INCY !#D (#STRIDE (Y))
END SUBROUTINE
END INTERFACE
Next the interface generator determines if this parameter is a work space parameter (step 446). A workspace parameter provides memory that will be used by the underlying F77 subprogram. This determination is made by examining the comments of the parameter in the source code. If this parameter is a workspace parameter, the interface generator inserts the WORK code-generator statement into the interface file (step 448). The WORK code-generator statement is defined as WORK(expression), where the "expression" indicates the size of the workspace.
TABLE 17
INTERFACE WORK
SUBROUTINE CWORK (N, ARRAY, WORK, IWORK)
INTEGER : : N !#D (#SIZE (ARRAY, #DIM=1))
COMPLEX : : ARRAY
REAL : : WORK (:) !#if((N.GT.0) , #WORK (N), #ELSE
(#WORK (N*2)))
REAL : : IWORK (:) !#WORK (N)
END SUBROUTINE
END INTERFACE
Next, the interface generator determines if more parameters remain to be processed (step 450), and if so, processing continues to step 412. Otherwise, the interface generator determines if more subprograms remain for processing (step 452), and if so, processing continues to step 408. If no more subprograms remain to be processed, processing ends. For an example of inserting code-generator statements into an interface file, consider the following. The CSTSV subprogram computes the solution to a complex system of linear equations A*X=B, where A is an N-by-N symmetric tridiagonal matrix and X and B are N-by-NRHS matrices. The following interface file is generated by examining the CSTSV F77 source to extract the parameter list and the parameter declarations.
INTERFACE
SUBROUTINE CSTSV (N, NRHS, L, D, SUBL, B, LDB, IPIV,
INFO)
INTEGER : : N
INTEGER : : NRHS
COMPLEX : : L (*)
COMPLEX : : D (*)
COMPLEX : : SUBL (*)
COMPLEX : : B (LDB, *)
INTEGER : : LDB
INTEGER : : IPIV (*)
INTEGER : : INFO
END SUBROUTINE
END INTERFACE
By parsing the comments in the source code, the interface generator can add code-generator statements to the interface file. For instance, the following example line in the F77 source code:
N (input) INTEGER
allows the interface generator to insert the #INPUT code-generator statement into the interface file associated with the parameter N. Also, the following exemplary F77 source code declarations:
D (input / output) COMPLEX array, dimension (N)
L (input / output) COMPLEX array, dimension (N-1)
SUBL (output) COMPLEX array, dimension (N-2)
NRHS (input) INTEGER
allow the interface generator to not only associate the #INOUT statement with the parameters D and L, but also the #OUTPUT statement can be associated with the SUBL parameter and the#INPUT statement to the NRHS parameter. In addition, the declaration of D gives the interface generator enough information to construct a default value for the parameter N. Furthermore, the following exemplary F77 declaration for B:
B (input/output) COMPLEX array, dimension (LDB, NRHS)
provides enough information to associate the #INOUT statement with B, create a default value for the LDB and NRHS parameters. This process continues until all the comments have been examined and code-generator statements generated. The final result is an interface file populated with code-generator statements.
INTERFACE
SUBROUTINE CSTSV (N, NRHS, L, D, SUBL, B, LDB, IPIV,
INFO)
INTEGER : : N !#INPUT, #D (#SIZE (D, #DIM=1))
INTEGER : : NRHS !#D (#SIZE (B, #DIM=2))
COMPLEX : : L (*) !#INOUT
COMPLEX : : D (*) !#INOUT
COMPLEX : : SUBL (*) !#OUTPUT
COMPLEX : : B (LDB, *) !#INOUT
INTEGER : : LDB !#D (#STRIDE (B, #DIM=2))
INTEGER : : IPIV (*) !#OUTPUT
INTEGER : : INFO !#INFO
END SUBROUTINE
END INTERFACE
FIGS. 5A and 5B depict a flowchart of the steps performed by the stub generator. The stub generator performs two passes through the interface file that has been marked up with the code-generator statements. The first pass discovers information regarding each subprogram and its parameters and begins to populate a hash table with such information. The second pass through each subprogram provides more detailed information to the hash table. Once the hash table has been populated, the stub generator generates stubs using this information. The first step performed by the stub generator is to select a subprogram (step 502). Next, the stub generator determines whether the subprogram is a subroutine (i.e., does not return a return code) or is a function (i.e., returns a return code) (step 504). Next, the stub generator records the name of the subprogram into a hash table, one entry for each subprogram (step 506). Each hash table entry has the following items of information, where items 2-14 are specified for each parameter of the subprogram: 1) Subprogram Name 2) Parameter Name 3) Type (logical, real, double, etc.) 4) Rank (shape) 5) Optional: true/false 6) Info: true/false or expression indicating whether an error has occurred. 7) Work: expression indicating amount of memory needed for this parameter. 8) Sizer: this parameter describes the size of another parameter, the name of that parameter is stored in this field. 9) Mysizer: if another parameter is a sizer for this parameter, that parameter's name is stored in this field. 10) Not here: the source code that needs to be inserted into the stub if parameter is missing. 11) Here: source code to be inserted if the parameter exists (e.g., an info parameter causes the checking of a parameter after execution of the subprogram to see if an error code is set). 12) Strider: if this parameter is a strider for another parameter, then its name is stored in this field. 13) Mystrider: if another parameter acts as the strider for this parameter, then its name is stored in this entry. 14) Intent: undefined, input, output, or i/o. After recording the name, the stub generator examines the parameter list to determine the number of parameters as well as their name for the subprogram and stores this information into the hash table (step 508). The stub generator then identifies the details of each parameter including its shape and type and stores this into the hash table (step 510). After identifying the parameter details, the stub generator determines if there are more subprograms, and if so, proceeds to step 502. Otherwise, the stub generator proceeds to the second pass by selecting a subprogram (step 514). Next, the stub generator processes the code-generator statements by inserting various information into the hash table. The following table indicates the code-generator statements and the processing that occurs for each one:
Code-Generator
Statement Processing That Occurs
D (default expression) Put expression into "not here" field of hash
table and set optional to true.
Here (expression) Straight copy from "here" code-generator
statement to "here" field in hash table.
If (expression, Copy entire expression into "nothere," so at
default1, runtime the correct default is set.
else, default2) Set optional to true.
Info If this code-generator statement doesn't
appear, set this field to false. Copy expression
into Info part of hash table. If there is no
expression, set Info to true.
Inout, Input, Output Set the intent field accordingly.
Range Set to value in Rank.
Size Copy this value to "sizer" entry.
Stride Copy this value to "strider" entry.
Work Copy of expression to the "work" entry.
After processing the code-generator statements, the stub generator generates interfaces (step 518). In this step, the stub generator generates one interface for each legal combination of parameters given their optionality. This list is provided next to the "G" code-generator statements. Each interface contains a declaration for a given combination of parameters and follows the format described above with respect to Table 1. After generating the interfaces, the stub generator groups families of interfaces together to form a single interface (step 520). An example of a single interface follows:
INTERFACE ABC
SUBROUTINE ABC1
. . .
END SUBROUTINE
SUBROUTINE ABC2
. . .
END SUBROUTINE
. . .
SUBROUTINE ABCN
END SUBROUTINE
END INTERFACE
Next, the stub generator generates the stub code for each interface (step 522). For an interface with a complete parameter list, the stub code simply invokes the F77 subprogram. For an interface with an incomplete parameter list, the stub code determines which parameters are missing and then inserts the appropriate information given the "not here" entry in the hash table. If the "info" entry is undefined or true, then the stub code need do nothing. If, however, "info" contains an expression, then code is inserted to check the F77 code return value and generate an error code if appropriate. If one of the parameters is a work parameter, then the stub routine allocates the appropriate memory before the F77 call and deallocates the memory afterwards. After generating the stub code, the stub code generator determines if there are more subprograms (step 524) and, if so, continues to step 502. Otherwise, processing ends. As part of step 522 in FIG. 5B, when generating stub code, the stub generator performs an optimization to avoid significant processing overhead and to reduce memory utilization. This optimization generates the stubs in such a way as to avoid gather and scatter. In F90, arrays are referenced by using a dope vector. A "dope vector" is a data structure containing three elements that describe an array: a pointer to the array, a length of each dimension of the array, and the stride for each dimension of the array. The declaration of the dope vector as written in the C programming language is provided below:
struct AV {
void *actual_origin; // This is a pointer to the data in
the array
unsigned extent [ ]; // This describes the length of each
long dimension
signed stride [ ]; // This describes the stride in each
long dimension
}
Like most non-F90 programming languages, F77 cannot handle dope vectors for referencing arrays. Thus, when a dope vector is attempting to be passed to an F77 subprogram, before the F77 subprogram is called, compiler-generated code is typically executed to perform a gather on the array to place the array in contiguous memory, thus producing a stride of one. And upon return from the F77 subprogram, compiler-generated code is executed to perform a scatter on the returned array, thus spacing out the array to its pre-gather stride. There are at least two problems created by this gather and scatter. First, the processing overhead associated with performing the gather and scatter operations adds significantly to the time required to perform the subprogram call. Second, when the arrays gather, temporary memory is allocated to store the gathered array. This additional memory allocation can have a variety of ramifications, ranging from slower execution to running out of system memory causing an abnormal termination. Thus, when generating the stub code, the stub generator identifies that a dope vector is being used to reference an array, and the stub generator creates code to call the subprogram in such a way as to avoid gather and scatter. The call is created by passing a pointer to the array itself (i.e., its memory address) with an indication of its length and stride as additional parameters. In F90, an array can be passed as a parameter in two ways: First, the array can be passed by merely indicating the array name (e.g., array), in which case what is actually passed is a reference to the array's dope vector. Second, a portion of the array may be passed. For instance, array (10:len:2) may be passedwhere "10" indicates the starting point in the array, "len" indicates the length of the array, and "2" indicates the stride. In this situation, a pointer to a dope vector is also passed. To prevent a dope vector from being passed as a parameter to the F77 subprogram, and hence avoid gather and scatter, the stub generator determines the length and the stride of the array and then passes as parameters to the subprogram (1) a pointer to the array, (2) the length of the array, and (3) the stride of the array. The subprograms utilized in accordance with methods and systems consistent with the present invention have a length parameter and a stride parameter usually associated with each array parameter. In the event that the length and stride are not passed into the stub as a parameter, their values can be obtained from the hash table. So, where "N" indicates the length of the array and 2 is the stride, the stub generator invokes the F77 subprogram "Do Nothing" in the following way to avoid gather and scatter: CALL DoNothing(N,%val(LOC(Array)),2) FIG. 6 depicts a flow chart of the steps performed by the stub generator to prevent a compiler from generating code to perform a gather and a scatter. The first step performed by the stub generator is to determine whether a dope vector is to be passed to a non-F90 subprogram (step 602). In this step, when generating the code for the stub, the stub generator will identify whether an array will be passed into the F77 subprogram, in which case since the stub is written in F90 code, it is implicit that a dope vector will be specified. Next, the stub generator determines if the length of the array has been specified as a parameter to the stub (step 604). If not, the stub generator generates code to determine the length of the array (step 606). In this step, the stub generator does so by accessing the hash table. The code that determines the length is contained in the not here field. It should be noted that if the array is multi-dimensional, the length for each dimension is obtained. If the length is specified or after generating code to determine the length, the stub generator determines if the stride has been specified as a parameter to the stub (step 608). If the stride has not been specified, the stub generator generates code to determine the stride (step 610). In this step, the stub generator accesses the not here field of the hash table to obtain the code that will determine the stride. In the event that the array is multi-dimensional, the stub generator determines the stride for each dimension. If the stride was specified or after generating code to determine the stride, the stub generator generates code to call the subprogram (step 612). In this step, the stub generator calls the subprogram by passing (1) a pointer to the array and not the dope vector, (2) a parameter indicating the length of the array, and (3) a parameter indicating the stride of the array. By specifying the array in this manner and avoiding the use of a dope vector, the compiler will not generate code to perform a gather and a scatter. Although the present invention has been described with reference to a preferred embodiment thereof, those skilled in the art will know of various changes in form and detail which may be made without departing from the spirit and scope of the present invention as defined in the appended claims and their full scope of equivalents.
|
Same subclass Same class Consider this |
||||||||||
