[llvm-commits] [llvm-gcc-4.2] r41269 - in /llvm-gcc-4.2/trunk/gcc: llvm-convert.cpp llvm-internal.h llvm-types.cpp

Duncan Sands baldrick at free.fr
Wed Aug 22 01:47:00 PDT 2007


Author: baldrick
Date: Wed Aug 22 03:46:59 2007
New Revision: 41269

URL: http://llvm.org/viewvc/llvm-project?rev=41269&view=rev
Log:
TREE_OVERFLOW is no longer reliable, so just try to
do something reasonable if imperfect for array types
with overflowed size or length.

Modified:
    llvm-gcc-4.2/trunk/gcc/llvm-convert.cpp
    llvm-gcc-4.2/trunk/gcc/llvm-internal.h
    llvm-gcc-4.2/trunk/gcc/llvm-types.cpp

Modified: llvm-gcc-4.2/trunk/gcc/llvm-convert.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/gcc/llvm-convert.cpp?rev=41269&r1=41268&r2=41269&view=diff

==============================================================================
--- llvm-gcc-4.2/trunk/gcc/llvm-convert.cpp (original)
+++ llvm-gcc-4.2/trunk/gcc/llvm-convert.cpp Wed Aug 22 03:46:59 2007
@@ -299,7 +299,6 @@
 /// isInt64 - Return true if t is an INTEGER_CST that fits in a 64 bit integer.
 /// If Unsigned is false, returns whether it fits in a int64_t.  If Unsigned is
 /// true, returns whether the value is non-negative and fits in a uint64_t.
-/// Always returns false for overflowed constants.
 bool isInt64(tree t, bool Unsigned) {
   if (HOST_BITS_PER_WIDE_INT == 64)
     return host_integerp(t, Unsigned);
@@ -307,7 +306,7 @@
     assert(HOST_BITS_PER_WIDE_INT == 32 &&
            "Only 32- and 64-bit hosts supported!");
     return
-      (TREE_CODE (t) == INTEGER_CST && !TREE_OVERFLOW (t))
+      (TREE_CODE (t) == INTEGER_CST)
       && ((TYPE_UNSIGNED(TREE_TYPE(t)) == Unsigned) ||
           // If the constant is signed and we want an unsigned result, check
           // that the value is non-negative.  If the constant is unsigned and
@@ -318,8 +317,8 @@
 
 /// getInt64 - Extract the value of an INTEGER_CST as a 64 bit integer.  If
 /// Unsigned is false, the value must fit in a int64_t.  If Unsigned is true,
-/// the value must be non-negative and fit in a uint64_t.  Must not be used on
-/// overflowed constants.  These conditions can be checked by calling isInt64.
+/// the value must be non-negative and fit in a uint64_t.  These conditions
+/// can be checked by calling isInt64.
 uint64_t getInt64(tree t, bool Unsigned) {
   assert(isInt64(t, Unsigned) && "invalid constant!");
   return getINTEGER_CSTVal(t);

Modified: llvm-gcc-4.2/trunk/gcc/llvm-internal.h
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/gcc/llvm-internal.h?rev=41269&r1=41268&r2=41269&view=diff

==============================================================================
--- llvm-gcc-4.2/trunk/gcc/llvm-internal.h (original)
+++ llvm-gcc-4.2/trunk/gcc/llvm-internal.h Wed Aug 22 03:46:59 2007
@@ -189,13 +189,12 @@
 /// isInt64 - Return true if t is an INTEGER_CST that fits in a 64 bit integer.
 /// If Unsigned is false, returns whether it fits in a int64_t.  If Unsigned is
 /// true, returns whether the value is non-negative and fits in a uint64_t.
-/// Always returns false for overflowed constants.
 bool isInt64(tree_node *t, bool Unsigned);
 
 /// getInt64 - Extract the value of an INTEGER_CST as a 64 bit integer.  If
 /// Unsigned is false, the value must fit in a int64_t.  If Unsigned is true,
-/// the value must be non-negative and fit in a uint64_t.  Must not be used on
-/// overflowed constants.  These conditions can be checked by calling isInt64.
+/// the value must be non-negative and fit in a uint64_t.  These conditions can
+/// be checked by calling isInt64.
 uint64_t getInt64(tree_node *t, bool Unsigned);
 
 /// isPassedByInvisibleReference - Return true if the specified type should be

Modified: llvm-gcc-4.2/trunk/gcc/llvm-types.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/gcc/llvm-types.cpp?rev=41269&r1=41268&r2=41269&view=diff

==============================================================================
--- llvm-gcc-4.2/trunk/gcc/llvm-types.cpp (original)
+++ llvm-gcc-4.2/trunk/gcc/llvm-types.cpp Wed Aug 22 03:46:59 2007
@@ -73,8 +73,15 @@
 // Note down LLVM type for GCC tree node.
 static const Type * llvm_set_type(tree Tr, const Type *Ty) {
 
+  // Require gcc and LLVM types to have the same size, if the gcc type has a
+  // constant size that fits in 64 bits.  Unfortunately we have to make an
+  // exception for huge arrays for which the size overflowed.
   assert(!TYPE_SIZE(Tr) || !Ty->isSized() || !isInt64(TYPE_SIZE(Tr), true) ||
          getInt64(TYPE_SIZE(Tr), true) == getTargetData().getTypeSizeInBits(Ty)
+         // Due to TREE_OVERFLOW not always being set correctly, we sometimes
+         // turn a gcc array with an overflowed size into a zero length LLVM
+         // array.
+         || (isa<ArrayType>(Ty) && !cast<ArrayType>(Ty)->getNumElements())
          && "LLVM type size doesn't match GCC type size!");
 
   unsigned &TypeSlot = LTypesMap[Ty];
@@ -302,10 +309,11 @@
       (!TYPE_SIZE(type) && isSequentialCompatible(type)) ||
 
       // Arrays with constant size map to LLVM arrays.  If the array has zero
-      // size then there can be two exotic cases: (1) the array might have zero
-      // length and a component type of variable size; or (2) the array could
-      // have variable length and a component type with zero size.  In both
-      // cases we convert to a zero length LLVM array.
+      // size then there can be three exotic cases: (1) the array might have
+      // zero length and a component type of variable size; or (2) the array
+      // could have variable length and a component type with zero size; or
+      // (3) the array size computation overflowed, giving an apparent size of
+      // zero.  In all cases we convert to a zero length LLVM array.
       (TYPE_SIZE(type) && isInt64(TYPE_SIZE(type), true))
     );
 }
@@ -840,18 +848,28 @@
         // to an unsized array of elements.
         NumElements = 0;
       } else if (!isInt64(length, true)) {
-        // A variable length array where the element type has size zero.  Turn
-        // it into a zero length array of the element type.
-        assert(integer_zerop(TYPE_SIZE(TREE_TYPE(type)))
-               && "variable length array has constant size!");
+        // A variable length array where the element type has size zero.
+        // Alternatively, the length may be negative due to overflow.
+        // Turn it into a zero length array of the element type.
         NumElements = 0;
       } else {
         // Normal array.
         NumElements = getInt64(length, true);
       }
 
-      return TypeDB.setType(type, ArrayType::get(ConvertType(TREE_TYPE(type)),
-                                                 NumElements));
+      const Type *Ty = ArrayType::get(ConvertType(TREE_TYPE(type)),
+                                      NumElements);
+
+      if (NumElements && TYPE_SIZE(type) && Ty->isSized() &&
+          getInt64(TYPE_SIZE(type), true) !=
+          getTargetData().getTypeSizeInBits(Ty))
+        // The type size and/or the array length overflowed.  It would be nice
+        // to detect this earlier as in llvm-gcc-4.0, but unfortunately
+        // TREE_OVERFLOW is no longer reliable.  Use a zero length array.
+        // This may result in wrong code, but that seems to be unavoidable.
+        Ty = ArrayType::get(ConvertType(TREE_TYPE(type)), 0);
+
+      return TypeDB.setType(type, Ty);
     }
 
     // This handles cases like "int A[n]" which have a runtime constant





More information about the llvm-commits mailing list