[mpich2-dev] [PATCH 1/1] Issue 4882: Fix assertions when negative displacements are used in datatypes

Jeff Parker jjparker at us.ibm.com
Tue Apr 22 11:13:42 CDT 2008


This patch contains a fix for problems with the BG/P MPI_Aint changes previously posted, as follows:

1. Some functions in bgp/comm/lib/mpi/mpich2/src/mpid/common/datatype/dataloop/segment_ops.c have displacements in buffer pointers.  The MPI_Aint changes that I previously made added assertions to ensure that arithmetic on buffer pointers does not overflow beyond the size of a pointer, and added casting of buffer pointers to MPI_Aints.  These changes are not correct when the buffer pointers contain negative offsets, and therefore have been removed.

2. The MPI_Aint configurable variables were using (long) and (unsigned long) as the arithmetic version of a pointer.  I changed these to use the new MPI_Pint and MPI_Puint datatypes.  This will generate the same code, but is the proper way to do this.

Signed-off-by: Jeff Parker <jjparker at us.ibm.com>
---
 lib/mpi/mpich2/configure.in                        |   36 +++---
 lib/mpi/mpich2/src/include/mpi.h.in                |    1 +
 lib/mpi/mpich2/src/include/mpiutil.h               |    2 +-
 .../mpid/common/datatype/dataloop/segment_ops.c    |  124 ++++++++++++++------
 4 files changed, 109 insertions(+), 54 deletions(-)

diff --git a/lib/mpi/mpich2/configure.in b/lib/mpi/mpich2/configure.in
index 2640d26..18f3938 100755
--- a/lib/mpi/mpich2/configure.in
+++ b/lib/mpi/mpich2/configure.in
@@ -5003,6 +5003,24 @@ MPI_PUINT="unsigned $MPI_AINT"
 AC_SUBST(MPI_PINT)
 AC_SUBST(MPI_PUINT)
 
+# Set:
+#   - MPI_AINT cast to a void*
+MPI_AINT_CAST_TO_VOID_PTR="(void*)(MPI_Pint)"
+#   - void* cast to an MPI_AINT
+MPI_VOID_PTR_CAST_TO_MPI_AINT="(MPI_Aint)(MPI_Puint)"
+#   - void* containing a signed displacement cast to an MPI_AINT
+MPI_PTR_DISP_CAST_TO_MPI_AINT="(MPI_Aint)(MPI_Pint)"
+#   - MPI_AINT cast to a long long for printing
+MPI_AINT_CAST_TO_LONG_LONG="(long long)"
+export MPI_AINT_CAST_TO_VOID_PTR
+export MPI_VOID_PTR_CAST_TO_MPI_AINT
+export MPI_PTR_DISP_CAST_TO_MPI_AINT
+export MPI_AINT_CAST_TO_LONG_LONG
+AC_SUBST(MPI_AINT_CAST_TO_VOID_PTR)
+AC_SUBST(MPI_VOID_PTR_CAST_TO_MPI_AINT)
+AC_SUBST(MPI_PTR_DISP_CAST_TO_MPI_AINT)
+AC_SUBST(MPI_AINT_CAST_TO_LONG_LONG)
+
 if test "$with_aint_size" == "0" ; then
     # use default size
     AC_MSG_RESULT([Default MPI_Aint $with_aint_size $MPI_SIZEOF_AINT])
@@ -5018,40 +5036,22 @@ if test "$with_aint_size" == "8" ; then
     MPI_AINT_FMT_DEC_SPEC="%lld"
     MPI_AINT_FMT_HEX_SPEC="%#llx"
 
-    MPI_AINT_CAST_TO_VOID_PTR="(void*)(long)"
-    MPI_VOID_PTR_CAST_TO_MPI_AINT="(MPI_Aint)(unsigned long)"
-    MPI_AINT_CAST_TO_LONG_LONG="(long long)"
     AC_DEFINE(HAVE_AINT_LARGER_THAN_FINT,1,[Define if addresses are larger than Fortran integers])
 
     export MPI_SIZEOF_AINT
     export MPI_AINT_FMT_DEC_SPEC MPI_AINT_FMT_HEX_SPEC
-    export MPI_AINT_CAST_TO_VOID_PTR
-    export MPI_VOID_PTR_CAST_TO_MPI_AINT
-    export MPI_AINT_CAST_TO_LONG_LONG
     AC_SUBST(MPI_AINT)
     AC_SUBST(MPI_AINT_FMT_DEC_SPEC)
     AC_SUBST(MPI_AINT_FMT_HEX_SPEC)
-    AC_SUBST(MPI_AINT_CAST_TO_VOID_PTR)
-    AC_SUBST(MPI_VOID_PTR_CAST_TO_MPI_AINT)
-    AC_SUBST(MPI_AINT_CAST_TO_LONG_LONG)
 else
     # use calculated MPI_Aint values
     AC_MSG_RESULT([Use configured MPI_Aint $with_aint_size])
-    MPI_AINT_CAST_TO_VOID_PTR="(void*)"
-    MPI_VOID_PTR_CAST_TO_MPI_AINT="(MPI_Aint)(unsigned long)"
-    MPI_AINT_CAST_TO_LONG_LONG="(long long)(unsigned long)"
 
     export MPI_SIZEOF_AINT
     export MPI_AINT_FMT_DEC_SPEC MPI_AINT_FMT_HEX_SPEC
-    export MPI_AINT_CAST_TO_VOID_PTR
-    export MPI_VOID_PTR_CAST_TO_MPI_AINT
-    export MPI_AINT_CAST_TO_LONG_LONG
     AC_SUBST(MPI_AINT)
     AC_SUBST(MPI_AINT_FMT_DEC_SPEC)
     AC_SUBST(MPI_AINT_FMT_HEX_SPEC)
-    AC_SUBST(MPI_AINT_CAST_TO_VOID_PTR)
-    AC_SUBST(MPI_VOID_PTR_CAST_TO_MPI_AINT)
-    AC_SUBST(MPI_AINT_CAST_TO_LONG_LONG)
 fi
 
 # If sizeof(mpi_aint) = sizeof(int), set this value
diff --git a/lib/mpi/mpich2/src/include/mpi.h.in b/lib/mpi/mpich2/src/include/mpi.h.in
index b275bb7..d623a5e 100644
--- a/lib/mpi/mpich2/src/include/mpi.h.in
+++ b/lib/mpi/mpich2/src/include/mpi.h.in
@@ -336,6 +336,7 @@ typedef @MPI_FINT@ MPI_Fint;
 #define MPI_AINT_FMT_HEX_SPEC "@MPI_AINT_FMT_HEX_SPEC@"
 #define MPI_AINT_CAST_TO_VOID_PTR @MPI_AINT_CAST_TO_VOID_PTR@
 #define MPI_VOID_PTR_CAST_TO_MPI_AINT @MPI_VOID_PTR_CAST_TO_MPI_AINT@
+#define MPI_PTR_DISP_CAST_TO_MPI_AINT @MPI_PTR_DISP_CAST_TO_MPI_AINT@
 #define MPI_AINT_CAST_TO_LONG_LONG @MPI_AINT_CAST_TO_LONG_LONG@
 
 /* Let ROMIO know that MPI_Offset is already defined */
diff --git a/lib/mpi/mpich2/src/include/mpiutil.h b/lib/mpi/mpich2/src/include/mpiutil.h
index 9df215c..bb9e550 100644
--- a/lib/mpi/mpich2/src/include/mpiutil.h
+++ b/lib/mpi/mpich2/src/include/mpiutil.h
@@ -105,6 +105,6 @@ int MPID_Abort( struct MPID_Comm *comm, int mpi_errno, int exit_code, const char
  * \param[in]  aint  Variable of type MPI_Aint
  */
 #define MPID_Ensure_Aint_fits_in_pointer( aint ) \
-  MPIU_Assert( (aint) == (MPI_Aint)(unsigned long) MPI_AINT_CAST_TO_VOID_PTR (aint) );
+  MPIU_Assert( (aint) == (MPI_Aint)(MPI_Puint) MPI_AINT_CAST_TO_VOID_PTR (aint) );
 
 #endif /* !defined(MPIUTIL_H_INCLUDED) */
diff --git a/lib/mpi/mpich2/src/mpid/common/datatype/dataloop/segment_ops.c b/lib/mpi/mpich2/src/mpid/common/datatype/dataloop/segment_ops.c
index 6fe799f..c7e5473 100644
--- a/lib/mpi/mpich2/src/mpid/common/datatype/dataloop/segment_ops.c
+++ b/lib/mpi/mpich2/src/mpid/common/datatype/dataloop/segment_ops.c
@@ -37,6 +37,7 @@ int PREPEND_PREFIX(Segment_contig_m2m)(DLOOP_Offset *blocks_p,
 
     if (paramp->direction == DLOOP_M2M_TO_USERBUF) {
 	/* Ensure that pointer increment fits in a pointer */
+	/* userbuf is a pointer (not a displacement) since it is being used on a memcpy */
 	MPID_Ensure_Aint_fits_in_pointer( (MPI_VOID_PTR_CAST_TO_MPI_AINT (paramp->userbuf)) + rel_off );
 	memcpy((char *) MPI_AINT_CAST_TO_VOID_PTR ((MPI_VOID_PTR_CAST_TO_MPI_AINT (paramp->userbuf)) + rel_off), 
 	       paramp->streambuf, 
@@ -44,11 +45,14 @@ int PREPEND_PREFIX(Segment_contig_m2m)(DLOOP_Offset *blocks_p,
     }
     else {
 	/* Ensure that pointer increment fits in a pointer */
+	/* userbuf is a pointer (not a displacement) since it is being used on a memcpy */
 	MPID_Ensure_Aint_fits_in_pointer( (MPI_VOID_PTR_CAST_TO_MPI_AINT (paramp->userbuf)) + rel_off );
 	memcpy(paramp->streambuf, 
 	       (char *) ( MPI_AINT_CAST_TO_VOID_PTR ((MPI_VOID_PTR_CAST_TO_MPI_AINT (paramp->userbuf)) + rel_off) ), 
 	       size);
     }
+    /* Ensure that pointer increment fits in a pointer */
+    /* streambuf is a pointer (not a displacement) since it was used on a memcpy */
     MPID_Ensure_Aint_fits_in_pointer( (MPI_VOID_PTR_CAST_TO_MPI_AINT (paramp->streambuf)) + size );
     paramp->streambuf += size;
     return 0;
@@ -76,6 +80,7 @@ int PREPEND_PREFIX(Segment_vector_m2m)(DLOOP_Offset *blocks_p,
     char *cbufp;
 
     /* Ensure that pointer increment fits in a pointer */
+    /* userbuf is a pointer (not a displacement) since it is being used for a memory copy */
     MPID_Ensure_Aint_fits_in_pointer( (MPI_VOID_PTR_CAST_TO_MPI_AINT (paramp->userbuf)) + rel_off );
     cbufp = (char*)( MPI_AINT_CAST_TO_VOID_PTR ( (MPI_VOID_PTR_CAST_TO_MPI_AINT (paramp->userbuf)) + rel_off ) );
     DLOOP_Handle_get_size_macro(el_type, el_size);
@@ -109,6 +114,8 @@ int PREPEND_PREFIX(Segment_vector_m2m)(DLOOP_Offset *blocks_p,
 	else {
 	    for (i=0; i < whole_count; i++) {
 		memcpy(cbufp, paramp->streambuf, ((DLOOP_Offset)blksz) * el_size);
+		/* Ensure that pointer increment fits in a pointer */
+		/* streambuf is a pointer (not a displacement) since it is being used for a memory copy */
 		MPID_Ensure_Aint_fits_in_pointer( (MPI_VOID_PTR_CAST_TO_MPI_AINT (paramp->streambuf)) + 
 						  ((DLOOP_Offset)blksz) * el_size );
 		paramp->streambuf += ((DLOOP_Offset)blksz) * el_size;
@@ -118,6 +125,8 @@ int PREPEND_PREFIX(Segment_vector_m2m)(DLOOP_Offset *blocks_p,
 	    }
 	    if (blocks_left) {
 		memcpy(cbufp, paramp->streambuf, ((DLOOP_Offset)blocks_left) * el_size);
+		/* Ensure that pointer increment fits in a pointer */
+		/* streambuf is a pointer (not a displacement) since it is being used for a memory copy */
 		MPID_Ensure_Aint_fits_in_pointer( (MPI_VOID_PTR_CAST_TO_MPI_AINT (paramp->streambuf)) + 
 						  ((DLOOP_Offset)blocks_left) * el_size );
 		paramp->streambuf += ((DLOOP_Offset)blocks_left) * el_size;
@@ -150,6 +159,8 @@ int PREPEND_PREFIX(Segment_vector_m2m)(DLOOP_Offset *blocks_p,
 	else {
 	    for (i=0; i < whole_count; i++) {
 		memcpy(paramp->streambuf, cbufp, (DLOOP_Offset)blksz * el_size);
+		/* Ensure that pointer increment fits in a pointer */
+		/* streambuf is a pointer (not a displacement) since it is being used for a memory copy */
 		MPID_Ensure_Aint_fits_in_pointer( (MPI_VOID_PTR_CAST_TO_MPI_AINT (paramp->streambuf)) + 
 						  (DLOOP_Offset)blksz * el_size );
 		paramp->streambuf += (DLOOP_Offset)blksz * el_size;
@@ -157,6 +168,8 @@ int PREPEND_PREFIX(Segment_vector_m2m)(DLOOP_Offset *blocks_p,
 	    }
 	    if (blocks_left) {
 		memcpy(paramp->streambuf, cbufp, (DLOOP_Offset)blocks_left * el_size);
+		/* Ensure that pointer increment fits in a pointer */
+		/* streambuf is a pointer (not a displacement) since it is being used for a memory copy */
 		MPID_Ensure_Aint_fits_in_pointer( (MPI_VOID_PTR_CAST_TO_MPI_AINT (paramp->streambuf)) + 
 						  (DLOOP_Offset)blocks_left * el_size );
 		paramp->streambuf += (DLOOP_Offset)blocks_left * el_size;
@@ -191,6 +204,8 @@ int PREPEND_PREFIX(Segment_blkidx_m2m)(DLOOP_Offset *blocks_p,
 
 	DLOOP_Assert(curblock < count);
 
+	/* Ensure that pointer increment fits in a pointer */
+	/* userbuf is a pointer (not a displacement) since it is being used for a memory copy */
 	MPID_Ensure_Aint_fits_in_pointer( (MPI_VOID_PTR_CAST_TO_MPI_AINT (paramp->userbuf)) + 
 					  rel_off + offsetarray[curblock] );
 	cbufp = (char*) MPI_AINT_CAST_TO_VOID_PTR
@@ -226,6 +241,8 @@ int PREPEND_PREFIX(Segment_blkidx_m2m)(DLOOP_Offset *blocks_p,
 	    memcpy(dest, src, (DLOOP_Offset)blocklen * el_size);
 	}
 
+	/* Ensure that pointer increment fits in a pointer */
+	/* streambuf is a pointer (not a displacement) since it is being used for a memory copy */
 	MPID_Ensure_Aint_fits_in_pointer( (MPI_VOID_PTR_CAST_TO_MPI_AINT (paramp->streambuf)) + 
 					  (DLOOP_Offset)blocklen * el_size );
 	paramp->streambuf += (DLOOP_Offset)blocklen * el_size;
@@ -262,6 +279,7 @@ int PREPEND_PREFIX(Segment_index_m2m)(DLOOP_Offset *blocks_p,
 	cur_block_sz = blockarray[curblock];
 
 	/* Ensure that pointer increment fits in a pointer */
+	/* userbuf is a pointer (not a displacement) since it is being used for a memory copy */
 	MPID_Ensure_Aint_fits_in_pointer( (MPI_VOID_PTR_CAST_TO_MPI_AINT (paramp->userbuf)) + 
 					  rel_off + offsetarray[curblock]);
 	cbufp = (char*) MPI_AINT_CAST_TO_VOID_PTR
@@ -297,6 +315,8 @@ int PREPEND_PREFIX(Segment_index_m2m)(DLOOP_Offset *blocks_p,
 	    memcpy(dest, src, cur_block_sz * el_size);
 	}
 
+	/* Ensure that pointer increment fits in a pointer */
+	/* streambuf is a pointer (not a displacement) since it is being used for a memory copy */
 	MPID_Ensure_Aint_fits_in_pointer( (MPI_VOID_PTR_CAST_TO_MPI_AINT (paramp->streambuf)) + 
 					  cur_block_sz * el_size );
 	paramp->streambuf += cur_block_sz * el_size;
@@ -612,14 +632,20 @@ static int DLOOP_Segment_contig_mpi_flatten(DLOOP_Offset *blocks_p,
     
     last_idx = paramp->index - 1;
     if (last_idx >= 0) {
-	MPID_Ensure_Aint_fits_in_pointer( paramp->disps[last_idx] + ((DLOOP_Offset)paramp->blklens[last_idx]) );
-	last_end = (char*) MPI_AINT_CAST_TO_VOID_PTR 
+	/* Since disps can be negative, we cannot use MPID_Ensure_Aint_fits_in_pointer to verify that
+	 * disps + blklens fits in a pointer.  Just let it truncate, if the sizeof a pointer is less 
+	 * than the sizeof an MPI_Aint.
+	 */
+	last_end = (char*) MPI_AINT_CAST_TO_VOID_PTR
 	           (paramp->disps[last_idx] + ((DLOOP_Offset)paramp->blklens[last_idx]));
     }
 
-    MPID_Ensure_Aint_fits_in_pointer( (MPI_VOID_PTR_CAST_TO_MPI_AINT (bufp)) + rel_off);
+    /* Since bufp can be a displacement and can be negative, we cannot use 
+     * MPID_Ensure_Aint_fits_in_pointer to ensure the sum fits in a pointer.
+     * Just let it truncate.
+     */
     if ((last_idx == paramp->length-1) &&
-	(last_end != ((char *) bufp + rel_off)))
+        (last_end != ((char *) bufp + rel_off)))
     {
 	/* we have used up all our entries, and this region doesn't fit on
 	 * the end of the last one.  setting blocks to 0 tells manipulation
@@ -634,7 +660,11 @@ static int DLOOP_Segment_contig_mpi_flatten(DLOOP_Offset *blocks_p,
 	paramp->blklens[last_idx] += size;
     }
     else {
-	paramp->disps[last_idx+1]   = MPI_VOID_PTR_CAST_TO_MPI_AINT ((char *) bufp + rel_off);
+	/* Since bufp can be a displacement and can be negative, we cannot use 
+	 * MPI_VOID_PTR_CAST_TO_MPI_AINT to cast the sum to a pointer.  Just let it
+	 * sign extend.
+	 */
+        paramp->disps[last_idx+1]   = MPI_PTR_DISP_CAST_TO_MPI_AINT bufp + rel_off;
 	paramp->blklens[last_idx+1] = size;
 	paramp->index++;
     }
@@ -689,17 +719,22 @@ static int DLOOP_Segment_vector_mpi_flatten(DLOOP_Offset *blocks_p,
 
 	last_idx = paramp->index - 1;
 	if (last_idx >= 0) {
-	    MPID_Ensure_Aint_fits_in_pointer( paramp->disps[last_idx] +
-					      (MPI_Aint)(paramp->blklens[last_idx]) );
-	    last_end = (char *) MPI_AINT_CAST_TO_VOID_PTR 
+	    /* Since disps can be negative, we cannot use MPID_Ensure_Aint_fits_in_pointer to verify that
+	     * disps + blklens fits in a pointer.  Nor can we use MPI_AINT_CAST_TO_VOID_PTR to cast the 
+	     * sum to a pointer.  Just let it truncate, if the sizeof a pointer is less than the sizeof
+	     * an MPI_Aint.
+	     */
+	    last_end = (char *) MPI_AINT_CAST_TO_VOID_PTR
 		       ( paramp->disps[last_idx] +
 			 (MPI_Aint)(paramp->blklens[last_idx]) );
 	}
 
-	MPID_Ensure_Aint_fits_in_pointer( MPI_VOID_PTR_CAST_TO_MPI_AINT bufp + rel_off );
-	if ((last_idx == paramp->length-1) &&
-	    (last_end != (char *) MPI_AINT_CAST_TO_VOID_PTR 
-	                 ( MPI_VOID_PTR_CAST_TO_MPI_AINT bufp + rel_off) ) )
+	/* Since bufp can be a displacement and can be negative, we cannot use 
+	 * MPID_Ensure_Aint_fits_in_pointer to ensure the sum fits in a pointer.
+	 * Just let it truncate.
+	 */
+        if ((last_idx == paramp->length-1) &&
+            (last_end != ((char *) bufp + rel_off)))
 	{
 	    /* we have used up all our entries, and this one doesn't fit on
 	     * the end of the last one.
@@ -712,14 +747,17 @@ static int DLOOP_Segment_vector_mpi_flatten(DLOOP_Offset *blocks_p,
 #endif
 	    return 1;
 	}
-	else if (last_idx >= 0 && (last_end == (char *) MPI_AINT_CAST_TO_VOID_PTR 
- 	                                       ( MPI_VOID_PTR_CAST_TO_MPI_AINT bufp + rel_off ) ) )
+        else if (last_idx >= 0 && (last_end == ((char *) bufp + rel_off)))
 	{
 	    /* add this size to the last vector rather than using up new one */
 	    paramp->blklens[last_idx] += size;
 	}
 	else {
-	    paramp->disps[last_idx+1]   = MPI_VOID_PTR_CAST_TO_MPI_AINT bufp + rel_off;
+	    /* Since bufp can be a displacement and can be negative, we cannot use 
+	     * MPI_VOID_PTR_CAST_TO_MPI_AINT to cast the sum to a pointer.  Just let it
+	     * sign extend.
+	     */
+            paramp->disps[last_idx+1]   = MPI_PTR_DISP_CAST_TO_MPI_AINT bufp + rel_off;
 	    paramp->blklens[last_idx+1] = size;
 	    paramp->index++;
 	}
@@ -773,15 +811,21 @@ static int DLOOP_Segment_blkidx_mpi_flatten(DLOOP_Offset *blocks_p,
 
 	last_idx = paramp->index - 1;
 	if (last_idx >= 0) {
-	    MPID_Ensure_Aint_fits_in_pointer( paramp->disps[last_idx] + ((DLOOP_Offset)paramp->blklens[last_idx]) );
-	    last_end = (char*) MPI_AINT_CAST_TO_VOID_PTR 
+	    /* Since disps can be negative, we cannot use MPID_Ensure_Aint_fits_in_pointer to verify that
+	     * disps + blklens fits in a pointer.  Nor can we use MPI_AINT_CAST_TO_VOID_PTR to cast the 
+	     * sum to a pointer.  Just let it truncate, if the sizeof a pointer is less than the sizeof
+	     * an MPI_Aint.
+	     */
+	    last_end = (char*) MPI_AINT_CAST_TO_VOID_PTR
 		       (paramp->disps[last_idx] + ((DLOOP_Offset)paramp->blklens[last_idx]));
 	}
 
-	MPID_Ensure_Aint_fits_in_pointer( (MPI_VOID_PTR_CAST_TO_MPI_AINT bufp) + rel_off );
-	if ((last_idx == paramp->length-1) &&
-	    (last_end != (char *) MPI_AINT_CAST_TO_VOID_PTR
-			 (MPI_VOID_PTR_CAST_TO_MPI_AINT bufp + rel_off) ))
+	/* Since bufp can be a displacement and can be negative, we cannot use 
+	 * MPID_Ensure_Aint_fits_in_pointer to ensure the sum fits in a pointer.
+	 * Just let it truncate.
+	 */
+        if ((last_idx == paramp->length-1) &&
+            (last_end != ((char *) bufp + rel_off)))
 	{
 	    /* we have used up all our entries, and this one doesn't fit on
 	     * the end of the last one.
@@ -794,15 +838,17 @@ static int DLOOP_Segment_blkidx_mpi_flatten(DLOOP_Offset *blocks_p,
 #endif
 	    return 1;
 	}
-	else if (last_idx >= 0 && (last_end == (char *) MPI_AINT_CAST_TO_VOID_PTR
-			                       (MPI_VOID_PTR_CAST_TO_MPI_AINT bufp + rel_off) ) )
+        else if (last_idx >= 0 && (last_end == ((char *) bufp + rel_off)))
 	{
 	    /* add this size to the last vector rather than using up new one */
 	    paramp->blklens[last_idx] += size;
 	}
 	else {
-	    paramp->disps[last_idx+1]   = (MPI_Aint) (MPI_VOID_PTR_CAST_TO_MPI_AINT bufp + 
-						      rel_off + offsetarray[last_idx+1]);
+	    /* Since bufp can be a displacement and can be negative, we cannot use 
+	     * MPI_VOID_PTR_CAST_TO_MPI_AINT to cast the sum to a pointer.  Just let it
+	     * sign extend.
+	     */
+            paramp->disps[last_idx+1]   = MPI_PTR_DISP_CAST_TO_MPI_AINT bufp + rel_off + offsetarray[last_idx+1];
 	    paramp->blklens[last_idx+1] = size;
 	    paramp->index++;
 	}
@@ -856,17 +902,22 @@ static int DLOOP_Segment_index_mpi_flatten(DLOOP_Offset *blocks_p,
 
 	last_idx = paramp->index - 1;
 	if (last_idx >= 0) {
-	    MPID_Ensure_Aint_fits_in_pointer( paramp->disps[last_idx] +
-					      (MPI_Aint)(paramp->blklens[last_idx]) );
-	    last_end = (char *) MPI_AINT_CAST_TO_VOID_PTR 
+	    /* Since disps can be negative, we cannot use MPID_Ensure_Aint_fits_in_pointer to verify that
+	     * disps + blklens fits in a pointer.  Nor can we use MPI_AINT_CAST_TO_VOID_PTR to cast the 
+	     * sum to a pointer.  Just let it truncate, if the sizeof a pointer is less than the sizeof
+	     * an MPI_Aint.
+	     */
+	    last_end = (char *) MPI_AINT_CAST_TO_VOID_PTR
 		       ( paramp->disps[last_idx] +
 			 (MPI_Aint)(paramp->blklens[last_idx]) );
 	}
 
-	MPID_Ensure_Aint_fits_in_pointer( (MPI_VOID_PTR_CAST_TO_MPI_AINT bufp) + rel_off );
-	if ((last_idx == paramp->length-1) &&
-	    (last_end != (char *) MPI_AINT_CAST_TO_VOID_PTR
-			 (MPI_VOID_PTR_CAST_TO_MPI_AINT bufp + rel_off) ))
+	/* Since bufp can be a displacement and can be negative, we cannot use 
+	 * MPID_Ensure_Aint_fits_in_pointer to ensure the sum fits in a pointer.
+	 * Just let it truncate.
+	 */
+        if ((last_idx == paramp->length-1) &&
+            (last_end != ((char *) bufp + rel_off)))
 	{
 	    /* we have used up all our entries, and this one doesn't fit on
 	     * the end of the last one.
@@ -879,14 +930,17 @@ static int DLOOP_Segment_index_mpi_flatten(DLOOP_Offset *blocks_p,
 #endif
 	    return 1;
 	}
-	else if (last_idx >= 0 && (last_end == (char *) MPI_AINT_CAST_TO_VOID_PTR
-			                       (MPI_VOID_PTR_CAST_TO_MPI_AINT bufp + rel_off) ))
+        else if (last_idx >= 0 && (last_end == ((char *) bufp + rel_off)))
 	{
 	    /* add this size to the last vector rather than using up new one */
 	    paramp->blklens[last_idx] += size;
 	}
 	else {
-	    paramp->disps[last_idx+1]   = (MPI_VOID_PTR_CAST_TO_MPI_AINT bufp) + rel_off + offsetarray[last_idx+1];
+	    /* Since bufp can be a displacement and can be negative, we cannot use 
+	     * MPI_VOID_PTR_CAST_TO_MPI_AINT to cast the sum to a pointer.  Just let it
+	     * sign extend.
+	     */
+            paramp->disps[last_idx+1]   = MPI_PTR_DISP_CAST_TO_MPI_AINT bufp + rel_off + offsetarray[last_idx+1];
 	    paramp->blklens[last_idx+1] = size;
 	    paramp->index++;
 	}
-- 
1.5.3.7




More information about the mpich2-dev mailing list