[llvm-commits] [dragonegg] r85915 - /dragonegg/trunk/llvm-types.cpp

Duncan Sands baldrick at free.fr
Tue Nov 3 10:57:43 PST 2009


Author: baldrick
Date: Tue Nov  3 12:57:42 2009
New Revision: 85915

URL: http://llvm.org/viewvc/llvm-project?rev=85915&view=rev
Log:
In a qualified union, the smallest field needs to be chosen.
This ensures that the LLVM type will be smaller than the
smallest possible size achievable by the GCC type (which is
of variable size), an important invariant for Ada.  While
there, for normal unions choose the field with the largest
size, rather than the field with the largest alignment.  I
think the previous alignment choice was an attempt to help
out the old constructor code, which had many assumptions
about alignment.

Modified:
    dragonegg/trunk/llvm-types.cpp

Modified: dragonegg/trunk/llvm-types.cpp
URL: http://llvm.org/viewvc/llvm-project/dragonegg/trunk/llvm-types.cpp?rev=85915&r1=85914&r2=85915&view=diff

==============================================================================
--- dragonegg/trunk/llvm-types.cpp (original)
+++ dragonegg/trunk/llvm-types.cpp Tue Nov  3 12:57:42 2009
@@ -1854,13 +1854,17 @@
 /// then we will add padding later on anyway to match union size.
 void TypeConverter::SelectUnionMember(tree type,
                                       StructTypeConversionInfo &Info) {
+  bool FindBiggest = TREE_CODE(type) != QUAL_UNION_TYPE;
+
   const Type *UnionTy = 0;
   tree GccUnionTy = 0;
   tree UnionField = 0;
-  unsigned MaxAlignSize = 0, MaxAlign = 0;
+  unsigned MinAlign = ~0U;
+  uint64_t BestSize = FindBiggest ? 0ULL : ~0ULL;
   for (tree Field = TYPE_FIELDS(type); Field; Field = TREE_CHAIN(Field)) {
     if (TREE_CODE(Field) != FIELD_DECL) continue;
-    assert(getFieldOffsetInBits(Field) == 0 && "Union with non-zero offset?");
+    assert(DECL_FIELD_OFFSET(Field) && integer_zerop(DECL_FIELD_OFFSET(Field))
+           && "Union with non-zero offset?");
 
     // Skip fields that are known not to be present.
     if (TREE_CODE(type) == QUAL_UNION_TYPE &&
@@ -1869,29 +1873,29 @@
 
     tree TheGccTy = TREE_TYPE(Field);
 
-    // Skip zero-length fields; ConvertType refuses to construct a type
-    // of size 0.
-    if (DECL_SIZE(Field) &&
-        TREE_CODE(DECL_SIZE(Field)) == INTEGER_CST &&
-        TREE_INT_CST_LOW(DECL_SIZE(Field)) == 0)
+    // Skip zero-length bitfields.  These are only used for setting the
+    // alignment.
+    if (DECL_BIT_FIELD(Field) && DECL_SIZE(Field) &&
+        integer_zerop(DECL_SIZE(Field)))
       continue;
 
     const Type *TheTy = ConvertType(TheGccTy);
-    unsigned Size  = Info.getTypeSize(TheTy);
     unsigned Align = Info.getTypeAlignment(TheTy);
+    uint64_t Size  = Info.getTypeSize(TheTy);
 
     adjustPaddingElement(GccUnionTy, TheGccTy);
 
-    // Select TheTy as union type if it is more aligned than any other.  If
-    // more than one field achieves the maximum alignment then choose the
-    // biggest.
-    if (UnionTy == 0 || Align > MaxAlign ||
-        (Align == MaxAlign && Size > MaxAlignSize)) {
+    // Select TheTy as union type if it is the biggest/smallest field (depending
+    // on the value of FindBiggest).  If more than one field achieves this size
+    // then choose the least aligned.
+    if ((Size == BestSize && Align < MinAlign) ||
+        (FindBiggest && Size > BestSize) ||
+        (!FindBiggest && Size < BestSize)) {
       UnionTy = TheTy;
       UnionField = Field;
       GccUnionTy = TheGccTy;
-      MaxAlignSize = Size;
-      MaxAlign = Align;
+      BestSize = Size;
+      MinAlign = Align;
     }
 
     // Skip remaining fields if this one is known to be present.





More information about the llvm-commits mailing list