[cfe-commits] [PATCH] Compile-time MPI_Datatype checking, type arguments in attributes

Dmitri Gribenko gribozavr at gmail.com
Sun May 13 08:04:54 PDT 2012


Hello,

I want to ask for a review of a new version of the patch that
implements this proposal.  Major changes are:
* compatibility with MPICH2 and MVAPICH2;
* support for checking layout-compatible types (like MPI_DOUBLE_INT).

=== Objective ===
Implement a set of annotations for MPI libraries and a diagnostic for
clang that checks that specified buffer type matches the passed
MPI_Datatype.

=== Background ===
Many MPI functions take a void* `buffer' and an MPI_Datatype (from
user's viewpoint -- an opaque identifier like MPI_INT, MPI_LONG etc.)
that describes how to send/receive that buffer.  For example,

int MPI_Send(void *buf, int count, MPI_Datatype datatype, int dest,
   int tag, MPI_Comm comm);

Users call it like this:
int *int_buf = ...;
MPI_Send(int_buf, 1, MPI_INT, ...);

Thus, user is on its own to ensure that buffer type matches the MPI_Datatype.

=== Annotation design ===
I decided to annotate MPI functions that have buffer arguments and
declarations of built-in `MPI_Datatype's.  Functions are easy: we use
mpi_typed_arg(buffer-arg-index, type-arg-index) attribute:

int MPI_Send(void *buf, int count, MPI_Datatype datatype, ...etc...)
   __attribute__(( mpi_typed_arg(1,3) ));

`MPI_Datatype's are trickier because there are at least two approaches
to declaring built-in datatypes.

OpenMPI-style declaration uses addresses of special objects as
built-in dataypes:

#define MPI_INT ((MPI_Datatype) &ompi_mpi_int)
extern struct ompi_predefined_datatype_t ompi_mpi_int
       __attribute__(( mpi_datatype(int) ));

MPICH2-style declaration uses magic numbers, so an additional
declaration is required to attach an attribute to:

#define MPI_INT ((MPI_Datatype) 0xa0000002)
static const MPI_Datatype mpich_mpi_int
             __attribute__(( mpi_datatype(int) )) = MPI_INT;

Matching C datatype for MPI_DATATYPE_NULL is void.

MPI also defines built-in datatypes like MPI_DOUBLE_INT which means
"any C datatype that is layout-compatible to struct { double d; int i;
}".  Attribute mpi_datatype_layout_compatible is used for these types.


While checking a function call we recognize mpi_datatype attribute if
datatype argument is either:
* an OpenMPI-style expression `((MPI_Datatype) &ident)';
* a MPICH2-style magic number `((MPI_Datatype) num)';
* a user-specified type `ident';
where ident has mpi_datatype or mpi_datatype_layout_compatible
attribute.

We emit a diagnostic in 2 cases.
Case 1.  (Any type except MPI_DATATYPE_NULL)  All of the following is true:
* buffer is not of `void *' type;
* buffer's element type doesn't match specified MPI_Datatype.

Case 2.  (MPI_DATATYPE_NULL)  All of the following is true:
* buffer is not of `void *' type;
* buffer is not a null pointer constant;
* mpi_datatype(void) was specified.

=== Clang modifications ===
We need to allow arbitrary types as attribute arguments.  From the
grammar of GNU attributes in lib/Parse/ParseDecl.cpp we see that there
is no easy way to pass a type argument to an attribute.  If I
understand everything correctly, GNU attribute grammar becomes
ambiguous in that case, so attribute argument parsing will be driven
by attribute name.  Fortunately, this modification is compatible with
C++11 attributes where attribute argument list is just a sequence of
tokens with balanced delimiters.

I added AttributeList::TypeArg member, the required AttributeList
constructor and factory method.  In Attr.td a new field,
HasTypeArgument, was added and a tablegen pass was implemented.  The
parser uses the generated table to decide if it should parse a list of
expressions or a type name.

The check itself is called from Sema::CheckFunctionCall, which seems
to be designed for similar purposes.

=== Compatibility ===
The annotation-based approach is compatible with OpenMPI, LAM MPI,
MPICH2 and MVAPICH2.  I already have a prototype patches for OpenMPI
and MPICH2.

=== Miscellaneous ===
There is an `iboutletcollection' attribute that takes a type argument.
It would be good if this implementation of type arguments could be
used for that, too.

Best regards,
Dmitri Gribenko

-- 
main(i,j){for(i=2;;i++){for(j=2;j<i;j++){if(!(i%j)){j=0;break;}}if
(j){printf("%d\n",i);}}} /*Dmitri Gribenko <gribozavr at gmail.com>*/
-------------- next part --------------
A non-text attachment was scrubbed...
Name: mpi-datatype-check-v2.patch
Type: application/octet-stream
Size: 51728 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20120513/553b4f96/attachment.obj>


More information about the cfe-commits mailing list