This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


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

Patch: Alpha32 POINTERS_EXTEND_UNSIGNED doesn't quite work right.


-- 

===================================================
Donn Terry                  mailto:donn@interix.com
Softway Systems, Inc.        http://www.interix.com
2850 McClelland Dr, Ste. 1800   Ft.Collins CO 80525
Tel: +1-970-204-9900           Fax: +1-970-204-9951
===================================================
Problem: Alpha32 POINTERS_EXTEND_UNSIGNED doesn't quite work right.

(N.B.  This fix brings the set of Alpha32 specific regression failures
very close to that for other Alphas; convergence appears achievable very
soon.)

Specific symptom (Alpha 32):
gcc/calls.c uses a flag value of (rtx)(HOST_WIDE_INT)-1, which does not
survive intact when returned as a function result (it gets truncated
to 0xffffffff, which is not -1 in 64 bits.)  This causes the unsorted/ex.c
regression to fail at -O3.  (This is an indirect effect of calls.c not
handling inlining correctly if it has the pointer sign extension bug.)

This is wrapped up in an issue of "what is the underlying type of a pointer"
that's discussed below, and in detail in prior mail.

Fix:
The patch to stor-layout.c is approximately as suggested by RTH.
(Note, in the CVS tree, only Alpha defines POINTERS_EXTEND_UNSIGNED).

This fix alone exposes a latent problem with an infinite recursion in
convert.c/c-convert.c.  (Subtitle: lather, rinse, repeat.)

    pointer_diff() calls convert (while setting up the MINUS).
    The operand being converted is an Alpha32 pointer (signed SI).
    (Other calls trigger the same problem.)

    Lather:
    Convert checks for various no-ops and then calls convert_to_integer.
    Convert to integer determines that it's converting from a
    pointer, and does expr=fold(build1(CONVERT...).

    That call to fold does nothing, and expr is returned as CONVERT.
    Convert_to_integer then calls itself with expr (now an integer
    because of the convert).

    This call to convert_to_integer determines that it has an
    integer and after checking that the current operation is not
    one of a few special cases determines if it is narrowing or
    widening the type.  If it's widening it (or it's a no-size-change)
    it converts this to a NOP_EXPR (so now we have NOP_EXPR(CONVERT(ptr...  ).

    Here we return to the outer convert_to_integer() which returns
    immediately to the original call in convert which is
    fold(convert_to_integer....

    Rinse:

    fold determines that this is NOP_EXPR(CONVERT(.... and treats
    that as a special case, see "Handle cases of two conversions
    in a row".  This ends up taking the branch where it discards
    the intermediate converison, Resulting in the object

    contained two levels down in the NOP_EXPR, which our original
    argument to convert, unmodified. 

    Repeat:

    convert() is then called on the resulting (unmodified) object.
    At this point, we recurse.

To break the recursion, we note that the "Handle cases..." code can
have the effect of undoing a conversion from a pointer to an integer
or vice-versa (because it treats pointers and integers equivalently).
If it is going to undo a conversion sequence that has a pointer on
one end and an integer on the other, don't allow that.

Fix: test for a change in type in fold().  (Note, the code there could
be hand-optimized a little, but this more clearly expresses the intent.)

Lastly, some comments to be inserted where POINTERS_EXTEND_UNSIGNED
is defined in alpha32.h and tm.texi.

Mon May 3 21:05:41 1999 Donn Terry (donn@interix.com)
			Richard Henderson (rth@cygnus.com)

	* stor-layout.c (layout_type): POINTERS_EXTEND_UNSIGNED sets
	signedness of pointer type.
	* fold-const.c (fold): Break recursion: pointer <-> integer
	conversion should not be undone by fold.
	* tm.texi (POINTERS_EXTEND_UNSIGNED): Document
	* config/alpha/alpha32.h (POINTERS_EXTEND_UNSIGNED): Document
	  

diff -urP egcs.source.old/gcc/stor-layout.c egcs.source/gcc/stor-layout.c
--- egcs.source.old/gcc/stor-layout.c	Fri Apr  9 10:02:54 1999
+++ egcs.source/gcc/stor-layout.c	Thu Apr 29 17:13:24 1999
@@ -795,7 +830,11 @@ layout_type (type)
       TYPE_MODE (type) = ptr_mode;
       TYPE_SIZE (type) = bitsize_int (POINTER_SIZE, 0L);
       TYPE_SIZE_UNIT (type) = size_int (POINTER_SIZE / BITS_PER_UNIT);
+#if defined(POINTERS_EXTEND_UNSIGNED)
+      TREE_UNSIGNED (type) = POINTERS_EXTEND_UNSIGNED;
+#else
       TREE_UNSIGNED (type) = 1;
+#endif
       TYPE_PRECISION (type) = POINTER_SIZE;
       break;
 
diff -urP egcs.source.old/gcc/fold-const.c egcs.source/gcc/fold-const.c
--- egcs.source.old/gcc/fold-const.c	Fri Apr  9 10:02:46 1999
+++ egcs.source/gcc/fold-const.c	Mon May  3 10:18:37 1999
@@ -4550,7 +4550,8 @@ fold (expr) 
 	      && (inter_float || inter_unsignedp == inside_unsignedp)
 	      && ! (final_prec != GET_MODE_BITSIZE (TYPE_MODE (final_type))
 		    && TYPE_MODE (final_type) == TYPE_MODE (inter_type))
-	      && ! final_ptr)
+	      && ! final_ptr
+	      && final_ptr == inside_ptr)
 	    return convert (final_type, TREE_OPERAND (TREE_OPERAND (t, 0), 0));
 
 	  /* If we have a sign-extension of a zero-extended value, we can
@@ -4581,7 +4582,8 @@ fold (expr) 
 	      && ! (final_ptr && inside_prec != inter_prec)
 	      && ! (final_prec != GET_MODE_BITSIZE (TYPE_MODE (final_type))
 		    && TYPE_MODE (final_type) == TYPE_MODE (inter_type))
-	      && ! final_ptr)
+	      && ! final_ptr
+	      && final_ptr == inside_ptr)
 	    return convert (final_type, TREE_OPERAND (TREE_OPERAND (t, 0), 0));
 	}
 
diff -urP egcs.source.old/gcc/tm.texi egcs.source/gcc/tm.texi
--- egcs.source.old/gcc/tm.texi	Sun Apr 18 20:18:04 1999
+++ egcs.source/gcc/tm.texi	Mon May  3 11:33:39 1999
@@ -735,6 +735,13 @@ A C expression whose value is nonzero if
 extended from being @code{POINTER_SIZE} bits wide to @code{Pmode} are to
 be zero-extended and zero if they are to be sign-extended.
 
+Under normal circumstances, the value should be 1, if the symbol is
+defined at all.  However, there are some architectures that explicitly
+define that pointer signs are to be sign-extended when held in a
+regster larger than required by the pointer size.  (32 bit Alpha is
+the only such known as of this writing.)  You should be certain that
+a value of 0 is required by the environment before setting it that way.
+
 You need not define this macro if the @code{POINTER_SIZE} is equal
 to the width of @code{Pmode}.
 
diff -urP egcs.source.old/gcc/config/alpha/alpha32.h egcs.source/gcc/config/alpha/alpha32.h
--- egcs.source.old/gcc/config/alpha/alpha32.h	Sun Apr 25 20:54:30 1999
+++ egcs.source/gcc/config/alpha/alpha32.h	Mon May  3 12:59:40 1999
@@ -36,7 +36,15 @@ Boston, MA 02111-1307, USA.  */
 /* WinNT (and thus Interix) use unsigned int */
 #define SIZE_TYPE "unsigned int"
 
-/* Pointer is 32 bits but the hardware has 64-bit addresses, sign extended. */
+/* Pointers are 32 bits, and are sign extended.
+   According to the Compaq/DEC architecture design and after rechecking
+   with their experts, they define any 32-bit quantity held in a 64 bit
+   register to be sign extended, specifically including pointers.
+   This implies that to retain proper semantics of pointers that there
+   is a discontinuity in the address space (such that no single object 
+   can cross the boundary) at 0x80000000.  This is known to be true
+   for VMS (using the default 32 bit pointers), and NT. */
+
 #undef POINTER_SIZE
 #define POINTER_SIZE 32
 #define POINTERS_EXTEND_UNSIGNED 0

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