[llvm-commits] [dragonegg] r149699 - /dragonegg/trunk/src/Constants.cpp

Duncan Sands baldrick at free.fr
Fri Feb 3 10:08:35 PST 2012


Author: baldrick
Date: Fri Feb  3 12:08:35 2012
New Revision: 149699

URL: http://llvm.org/viewvc/llvm-project?rev=149699&view=rev
Log:
Conversion of a constructor field can result in an element of the
wrong type.  The only case that happens in practice is mismatched
pointer types (see comment in patch for how this can happen).  So
just fix that up rather than doing more general (and expensive)
type conversion.  Also, now that record constructors are being
converted to the right type early, various other places that were
making aggregates nicer don't do anything useful (except in very
rare and dubious corner cases), and just burn compile time, so get
rid of them.

Modified:
    dragonegg/trunk/src/Constants.cpp

Modified: dragonegg/trunk/src/Constants.cpp
URL: http://llvm.org/viewvc/llvm-project/dragonegg/trunk/src/Constants.cpp?rev=149699&r1=149698&r2=149699&view=diff
==============================================================================
--- dragonegg/trunk/src/Constants.cpp (original)
+++ dragonegg/trunk/src/Constants.cpp Fri Feb  3 12:08:35 2012
@@ -681,60 +681,6 @@
   return Result;
 }
 
-/// OnlyDifferTrivially - Return 'true' if the given types do not differ in any
-/// significant way.  This means for example that reinterpreting a value of one
-/// of the types as having the other type does not lose any information.
-static bool OnlyDifferTrivially(Type *Ty1, Type *Ty2) {
-  if (Ty1 == Ty2)
-    return true;
-  Type::TypeID Id1 = Ty1->getTypeID(), Id2 = Ty2->getTypeID();
-
-  switch (Id1) {
-  default:
-    DieAbjectly("Unsupported type!");
-  case Type::PointerTyID:
-    // Different pointer types do not differ in any significant way.
-    return Id2 == Type::PointerTyID;
-  case Type::DoubleTyID:
-  case Type::FloatTyID:
-  case Type::FP128TyID:
-  case Type::IntegerTyID:
-  case Type::PPC_FP128TyID:
-  case Type::X86_FP80TyID:
-  case Type::X86_MMXTyID:
-    return false; // The types are already known to be different.
-  case Type::ArrayTyID: {
-    if (Id2 != Type::ArrayTyID)
-      return false;
-    ArrayType *ATy1 = cast<ArrayType>(Ty1), *ATy2 = cast<ArrayType>(Ty2);
-    if (ATy1->getNumElements() != ATy2->getNumElements())
-      return false;
-    return OnlyDifferTrivially(ATy1->getElementType(), ATy2->getElementType());
-  }
-  case Type::StructTyID: {
-    if (Id2 != Type::StructTyID)
-      return false;
-    StructType *STy1 = cast<StructType>(Ty1), *STy2 = cast<StructType>(Ty2);
-    if (STy1->isPacked() != STy2->isPacked() ||
-        STy1->getNumElements() != STy2->getNumElements())
-      return false;
-    for (unsigned i = 0, e = STy1->getNumElements(); i != e; ++i)
-      if (!OnlyDifferTrivially(STy1->getElementType(i),
-                               STy2->getElementType(i)))
-        return false;
-    return true;
-  }
-  case Type::VectorTyID: {
-    if (Id2 != Type::VectorTyID)
-      return false;
-    VectorType *VTy1 = cast<VectorType>(Ty1), *VTy2 = cast<VectorType>(Ty2);
-    if (VTy1->getNumElements() != VTy2->getNumElements())
-      return false;
-    return OnlyDifferTrivially(VTy1->getElementType(), VTy2->getElementType());
-  }
-  }
-}
-
 /// ConvertInitializerWithCast - Convert the initial value for a global variable
 /// to an equivalent LLVM constant then cast to the given type if both the type
 /// and the initializer are scalar, or if the initializer's type only differs in
@@ -748,17 +694,12 @@
   // pretty much anything.
   Constant *C = ConvertInitializerImpl(exp, Folder);
 
-  // If casting to or from an aggregate and the types only differ in a trivial
-  // way then reinterpret the initializer as having the desired type.  If the
-  // types differ significantly then this is probably something like a struct
-  // ending in a flexible array being initialized with a struct ending in an
-  // array of some definite size, so just return the initializer as is.
-  if (AGGREGATE_TYPE_P(type) || AGGREGATE_TYPE_P(TREE_TYPE(exp))) {
-    Type *DestTy = ConvertType(type);
-    if (OnlyDifferTrivially(C->getType(), DestTy))
-      return InterpretAsType(C, DestTy, 0, Folder);
+  // If casting to or from an aggregate then just return the initializer as is.
+  // If the types differ then this is probably something like a struct ending in
+  // a flexible array being initialized with a struct ending in an array of some
+  // definite size.
+  if (AGGREGATE_TYPE_P(type) || AGGREGATE_TYPE_P(TREE_TYPE(exp)))
     return C;
-  }
 
   // Scalar to scalar cast.  This is where the implicit scalar casts that GCC
   // permits are made explicit.
@@ -1368,11 +1309,23 @@
   if (StructType *STy = dyn_cast<StructType>(Ty))
     if (STy->isPacked() == Pack && STy->getNumElements() == Elts.size()) {
       bool EltTypesMatch = true;
-      for (unsigned i = 0, e = Elts.size(); i != e; ++i)
-        if (Elts[i]->getType() != STy->getElementType(i)) {
-          EltTypesMatch = false;
-          break;
+      for (unsigned i = 0, e = Elts.size(); i != e; ++i) {
+        Type *EltTy = Elts[i]->getType();
+        Type *FieldTy = STy->getElementType(i);
+        if (EltTy == FieldTy)
+          continue;
+        // When a recursive record type is converted, some of its pointer fields
+        // may be converted to the artifical type {}* to break the recursion. As
+        // type converting the field directly gives the proper pointer type, the
+        // result is a mismatch between the field and element types.  Fix it up.
+        if (EltTy->isPointerTy() && FieldTy->isPointerTy()) {
+          Elts[i] = Folder.CreateBitCast(Elts[i], FieldTy);
+          continue;
         }
+        // Too hard, just give up.
+        EltTypesMatch = false;
+        break;
+      }
       if (EltTypesMatch)
         return ConstantStruct::get(STy, Elts);
     }
@@ -1478,10 +1431,9 @@
     break;
   }
 
-  // Make the IR easier to read by converting the bunch of bytes returned by
-  // ConvertCST into a less surprising type when it is safe to do so.
-  if (!AGGREGATE_TYPE_P(TREE_TYPE(exp)) ||
-      OnlyDifferTrivially(Init->getType(), ConvertType(TREE_TYPE(exp))))
+  // Make the IR easier to read by returning a constant of the expected type if
+  // it is safe and efficient to do so.
+  if (!AGGREGATE_TYPE_P(TREE_TYPE(exp)))
     Init = InterpretAsType(Init, ConvertType(TREE_TYPE(exp)), 0, Folder);
 
 #ifndef NDEBUG





More information about the llvm-commits mailing list