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

Bob Wilson bob.wilson at apple.com
Wed Sep 23 09:41:34 PDT 2009


Author: bwilson
Date: Wed Sep 23 11:41:34 2009
New Revision: 82630

URL: http://llvm.org/viewvc/llvm-project?rev=82630&view=rev
Log:
Improve handling of bitfields in unions by sharing more of the code that
handles bitfields in structs.  Radar 7226434.

The immediate problem is that a union containing only a bitfield may cause
an assertion failure.  GCC sets the TREE_TYPE of a field to the smallest type
that contains the bitfield, and llvm had just been using that type (except
for a special case that Dale added in svn r47655 to handle bool bitfields on
PowerPC).  For a 24-bit field on ARM, TREE_TYPE was 32 bits but the size of
the union was only 24 bits, and this caused an assertion failure.  (We didn't
see this on X86 because the minimum field alignment for integer types is 32
bits, so the union size was rounded up to 32 bits.)

The struct conversion code already handles all of this, so I merged the
ConvertUNION method into ConvertRecord to reuse all the existing logic.
I also changed ConvertUnionCONSTRUCTOR to reuse a lot of the code from
ConvertRecordCONSTRUCTOR.

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=82630&r1=82629&r2=82630&view=diff

==============================================================================
--- llvm-gcc-4.2/trunk/gcc/llvm-convert.cpp (original)
+++ llvm-gcc-4.2/trunk/gcc/llvm-convert.cpp Wed Sep 23 11:41:34 2009
@@ -7828,28 +7828,51 @@
   assert(VEC_length(constructor_elt, elt) == 1
          && "Union CONSTRUCTOR with multiple elements?");
 
-  std::vector<Constant*> Elts;
+  ConstantLayoutInfo LayoutInfo(getTargetData());
+
   // Convert the constant itself.
-  Elts.push_back(Convert(VEC_index(constructor_elt, elt, 0)->value));
+  Constant *Val = Convert(VEC_index(constructor_elt, elt, 0)->value);
+
+  // Unions are initialized using the first member field.  Find it.
+  tree Field = TYPE_FIELDS(TREE_TYPE(exp));
+  assert(Field && "cannot initialize union with no fields");
+  while (TREE_CODE(Field) != FIELD_DECL) {
+    Field = TREE_CHAIN(Field);
+    assert(Field && "cannot initialize union with no fields");
+  }
+
+  // If this is a non-bitfield value, just slap it onto the end of the struct
+  // with the appropriate padding etc.  If it is a bitfield, we have more
+  // processing to do.
+  if (!isBitfield(Field))
+    LayoutInfo.AddFieldToRecordConstant(Val, 0);
+  else {
+    // Bitfields can only be initialized with constants (integer constant
+    // expressions).
+    ConstantInt *ValC = cast<ConstantInt>(Val);
+    uint64_t FieldSizeInBits = getInt64(DECL_SIZE(Field), true);
+    uint64_t ValueSizeInBits = Val->getType()->getPrimitiveSizeInBits();
+
+    assert(ValueSizeInBits >= FieldSizeInBits &&
+           "disagreement between LLVM and GCC on bitfield size");
+    if (ValueSizeInBits != FieldSizeInBits) {
+      // Fields are allowed to be smaller than their type.  Simply discard
+      // the unwanted upper bits in the field value.
+      APInt ValAsInt = ValC->getValue();
+      ValC = ConstantInt::get(Context, ValAsInt.trunc(FieldSizeInBits));
+    }
+    LayoutInfo.AddBitFieldToRecordConstant(ValC, 0);
+  }
 
   // If the union has a fixed size, and if the value we converted isn't large
   // enough to fill all the bits, add a zero initialized array at the end to pad
   // it out.
-  tree UnionType = TREE_TYPE(exp);
-  if (TYPE_SIZE(UnionType) && TREE_CODE(TYPE_SIZE(UnionType)) == INTEGER_CST) {
-    uint64_t UnionSize = ((uint64_t)TREE_INT_CST_LOW(TYPE_SIZE(UnionType))+7)/8;
-    uint64_t InitSize = getTargetData().getTypeAllocSize(Elts[0]->getType());
-    if (UnionSize != InitSize) {
-      const Type *FillTy;
-      assert(UnionSize > InitSize && "Init shouldn't be larger than union!");
-      if (UnionSize - InitSize == 1)
-        FillTy = Type::getInt8Ty(Context);
-      else
-        FillTy = ArrayType::get(Type::getInt8Ty(Context), UnionSize - InitSize);
-      Elts.push_back(Constant::getNullValue(FillTy));
-    }
-  }
-  return ConstantStruct::get(Context, Elts, false);
+  tree UnionTypeSizeTree = TYPE_SIZE(TREE_TYPE(exp));
+  if (UnionTypeSizeTree && TREE_CODE(UnionTypeSizeTree) == INTEGER_CST)
+    LayoutInfo.HandleTailPadding(getInt64(UnionTypeSizeTree, true));
+
+  return ConstantStruct::get(Context, LayoutInfo.ResultElts,
+                             LayoutInfo.StructIsPacked);
 }
 
 //===----------------------------------------------------------------------===//

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=82630&r1=82629&r2=82630&view=diff

==============================================================================
--- llvm-gcc-4.2/trunk/gcc/llvm-internal.h (original)
+++ llvm-gcc-4.2/trunk/gcc/llvm-internal.h Wed Sep 23 11:41:34 2009
@@ -168,6 +168,7 @@
   void SetFieldIndex(tree_node *field_decl, unsigned int Index);
   bool DecodeStructFields(tree_node *Field, StructTypeConversionInfo &Info);
   void DecodeStructBitField(tree_node *Field, StructTypeConversionInfo &Info);
+  void SelectUnionMember(tree_node *type, StructTypeConversionInfo &Info);
 };
 
 extern TypeConverter *TheTypeConverter;

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=82630&r1=82629&r2=82630&view=diff

==============================================================================
--- llvm-gcc-4.2/trunk/gcc/llvm-types.cpp (original)
+++ llvm-gcc-4.2/trunk/gcc/llvm-types.cpp Wed Sep 23 11:41:34 2009
@@ -703,9 +703,9 @@
     debug_tree(type);
     abort();
   case VOID_TYPE:   return SET_TYPE_LLVM(type, Type::getVoidTy(Context));
-  case RECORD_TYPE: return ConvertRECORD(type, orig_type);
+  case RECORD_TYPE:
   case QUAL_UNION_TYPE:
-  case UNION_TYPE:  return ConvertUNION(type, orig_type);
+  case UNION_TYPE:  return ConvertRECORD(type, orig_type);
   case BOOLEAN_TYPE: {
     if (const Type *Ty = GET_TYPE_LLVM(type))
       return Ty;
@@ -2033,10 +2033,86 @@
   Info.addNewBitField(FieldSizeInBits, FirstUnallocatedByte);
 }
 
+/// UnionHasOnlyZeroOffsets - Check if a union type has only members with
+/// offsets that are zero, e.g., no Fortran equivalences.
+static bool UnionHasOnlyZeroOffsets(tree type) {
+  for (tree Field = TYPE_FIELDS(type); Field; Field = TREE_CHAIN(Field)) {
+    if (TREE_CODE(Field) != FIELD_DECL) continue;
+    if (getFieldOffsetInBits(Field) != 0)
+      return false;
+  }
+  return true;
+}
 
-/// ConvertRECORD - We know that 'type' is a RECORD_TYPE: convert it to an LLVM
-/// type.
-//  A note on C++ virtual base class layout.  Consider the following example:
+/// SelectUnionMember - Find the union member with the largest aligment.  If
+/// there are multiple types with the same alignment, select the one with
+/// the largest size. If the type with max. align is smaller than other types,
+/// then we will add padding later on anyway to match union size.
+void TypeConverter::SelectUnionMember(tree type,
+                                      StructTypeConversionInfo &Info) {
+  const Type *UnionTy = 0;
+  tree GccUnionTy = 0;
+  tree UnionField = 0;
+  unsigned MaxAlignSize = 0, MaxAlign = 0;
+  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?");
+
+    // Skip fields that are known not to be present.
+    if (TREE_CODE(type) == QUAL_UNION_TYPE &&
+        integer_zerop(DECL_QUALIFIER(Field)))
+      continue;
+
+    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)
+      continue;
+
+    const Type *TheTy = ConvertType(TheGccTy);
+    unsigned Size  = Info.getTypeSize(TheTy);
+    unsigned Align = Info.getTypeAlignment(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)) {
+      UnionTy = TheTy;
+      UnionField = Field;
+      GccUnionTy = TheGccTy;
+      MaxAlignSize = Size;
+      MaxAlign = Align;
+    }
+
+    // Skip remaining fields if this one is known to be present.
+    if (TREE_CODE(type) == QUAL_UNION_TYPE &&
+        integer_onep(DECL_QUALIFIER(Field)))
+      break;
+  }
+
+  if (UnionTy) {            // Not an empty union.
+    if (8 * Info.getTypeAlignment(UnionTy) > TYPE_ALIGN(type))
+      Info.markAsPacked();
+
+    if (isBitfield(UnionField)) {
+      unsigned FieldSizeInBits = TREE_INT_CST_LOW(DECL_SIZE(UnionField));
+      Info.addNewBitField(FieldSizeInBits, 0);
+    } else {
+      Info.allFieldsAreNotBitFields();
+      Info.addElement(UnionTy, 0, Info.getTypeSize(UnionTy));
+    }
+  }
+}
+
+/// ConvertRECORD - Convert a RECORD_TYPE, UNION_TYPE or QUAL_UNION_TYPE to
+/// an LLVM type.
+// A note on C++ virtual base class layout.  Consider the following example:
 // class A { public: int i0; };
 // class B : public virtual A { public: int i1; };
 // class C : public virtual A { public: int i2; };
@@ -2069,9 +2145,11 @@
       return Ty;
   }
 
+  bool IsStruct = (TREE_CODE(type) == RECORD_TYPE);
   if (TYPE_SIZE(type) == 0) {   // Forward declaration?
     const Type *Ty = OpaqueType::get(Context);
-    TheModule->addTypeName(GetTypeName("struct.", orig_type), Ty);
+    TheModule->addTypeName(GetTypeName(IsStruct ? "struct." : "union.",
+                                       orig_type), Ty);
     return TypeDB.setType(type, Ty);
   }
 
@@ -2087,29 +2165,40 @@
   // of fields bear some resemblance to reality.  Also alter any fields that
   // are less aligned than their type, as the type may not get tail padding
   // in this case.
-  FixUpFields(type);
-
-  // Convert over all of the elements of the struct.
-  bool retryAsPackedStruct = false;
-  for (tree Field = TYPE_FIELDS(type); Field; Field = TREE_CHAIN(Field)) {
-    if (DecodeStructFields(Field, *Info) == false) {
-      retryAsPackedStruct = true;
-      break;
-    }
-  }
+  if (IsStruct)
+    FixUpFields(type);
 
-  if (retryAsPackedStruct) {
-    delete Info;
-    Info = new StructTypeConversionInfo(*TheTarget, TYPE_ALIGN(type) / 8, true);
+  // Workaround to get Fortran EQUIVALENCE working.
+  // TODO: Unify record and union logic and handle this optimally.
+  bool HasOnlyZeroOffsets = (!IsStruct && UnionHasOnlyZeroOffsets(type));
+  if (HasOnlyZeroOffsets) {
+    SelectUnionMember(type, *Info);
+  } else {
+    // Convert over all of the elements of the struct.
+    bool retryAsPackedStruct = false;
     for (tree Field = TYPE_FIELDS(type); Field; Field = TREE_CHAIN(Field)) {
       if (DecodeStructFields(Field, *Info) == false) {
-        assert(0 && "Unable to decode struct fields.");
+        retryAsPackedStruct = true;
+        break;
+      }
+    }
+
+    if (retryAsPackedStruct) {
+      delete Info;
+      Info = new StructTypeConversionInfo(*TheTarget, TYPE_ALIGN(type) / 8,
+                                          true);
+      for (tree Field = TYPE_FIELDS(type); Field; Field = TREE_CHAIN(Field)) {
+        if (DecodeStructFields(Field, *Info) == false) {
+          assert(0 && "Unable to decode struct fields.");
+        }
       }
     }
   }
 
-  // If the LLVM struct requires explicit tail padding to be the same size as
-  // the GCC struct, insert tail padding now.  This handles, e.g., "{}" in C++.
+  // Insert tail padding if the LLVM struct requires explicit tail padding to
+  // be the same size as the GCC struct or union.  This handles, e.g., "{}" in
+  // C++, and cases where a union has larger alignment than the largest member
+  // does.
   if (TYPE_SIZE(type) && TREE_CODE(TYPE_SIZE(type)) == INTEGER_CST) {
     uint64_t GCCTypeSize = getInt64(TYPE_SIZE_UNIT(type), true);
     uint64_t LLVMStructSize = Info->getSizeAsLLVMStruct();
@@ -2131,26 +2220,24 @@
         if (((GCCTypeSize-LLVMStructSize) % 4) == 0 &&
             (Info->getAlignmentAsLLVMStruct() %
              Info->getTypeAlignment(Type::getInt32Ty(Context))) == 0) {
-          // insert array of i32
-          unsigned Int32ArraySize = (GCCTypeSize-LLVMStructSize)/4;
+          // Insert array of i32.
+          unsigned Int32ArraySize = (GCCTypeSize-LLVMStructSize) / 4;
           const Type *PadTy =
             ArrayType::get(Type::getInt32Ty(Context), Int32ArraySize);
           Info->addElement(PadTy, GCCTypeSize - LLVMLastElementEnd,
                            Int32ArraySize, true /* Padding Element */);
         } else {
-          const Type *PadTy =
-            ArrayType::get(Type::getInt8Ty(Context), GCCTypeSize-LLVMStructSize);
+          const Type *PadTy = ArrayType::get(Type::getInt8Ty(Context),
+                                             GCCTypeSize-LLVMStructSize);
           Info->addElement(PadTy, GCCTypeSize - LLVMLastElementEnd,
                            GCCTypeSize - LLVMLastElementEnd,
                            true /* Padding Element */);
-
         }
       }
     }
   } else
     Info->RemoveExtraBytes();
 
-
   // Now that the LLVM struct is finalized, figure out a safe place to index to
   // and set index values for each FieldDecl that doesn't start at a variable
   // offset.
@@ -2158,45 +2245,52 @@
   for (tree Field = TYPE_FIELDS(type); Field; Field = TREE_CHAIN(Field))
     if (TREE_CODE(Field) == FIELD_DECL &&
         TREE_CODE(DECL_FIELD_OFFSET(Field)) == INTEGER_CST) {
-      uint64_t FieldOffsetInBits = getFieldOffsetInBits(Field);
-      tree FieldType = getDeclaredType(Field);
-      const Type *FieldTy = ConvertType(FieldType);
-
-      // If this is a bitfield, we may want to adjust the FieldOffsetInBits to
-      // produce safe code.  In particular, bitfields will be loaded/stored as
-      // their *declared* type, not the smallest integer type that contains
-      // them.  As such, we need to respect the alignment of the declared type.
-      if (isBitfield(Field)) {
-        // If this is a bitfield, the declared type must be an integral type.
-        unsigned BitAlignment = Info->getTypeAlignment(FieldTy)*8;
-
-        FieldOffsetInBits &= ~(BitAlignment-1ULL);
-        // When we fix the field alignment, we must restart the FieldNo search
-        // because the FieldOffsetInBits can be lower than it was in the
-        // previous iteration.
-        CurFieldNo = 0;
-
-        // Skip 'int:0', which just affects layout.
-        if (integer_zerop(DECL_SIZE(Field)))
-          continue;
-      }
+      if (HasOnlyZeroOffsets) {
+        // Set the field idx to zero for all members of a union.
+        SetFieldIndex(Field, 0);
+      } else {
+        uint64_t FieldOffsetInBits = getFieldOffsetInBits(Field);
+        tree FieldType = getDeclaredType(Field);
+        const Type *FieldTy = ConvertType(FieldType);
+
+        // If this is a bitfield, we may want to adjust the FieldOffsetInBits
+        // to produce safe code.  In particular, bitfields will be
+        // loaded/stored as their *declared* type, not the smallest integer
+        // type that contains them.  As such, we need to respect the alignment
+        // of the declared type.
+        if (isBitfield(Field)) {
+          // If this is a bitfield, the declared type must be an integral type.
+          unsigned BitAlignment = Info->getTypeAlignment(FieldTy)*8;
+
+          FieldOffsetInBits &= ~(BitAlignment-1ULL);
+          // When we fix the field alignment, we must restart the FieldNo
+          // search because the FieldOffsetInBits can be lower than it was in
+          // the previous iteration.
+          CurFieldNo = 0;
+
+          // Skip 'int:0', which just affects layout.
+          if (integer_zerop(DECL_SIZE(Field)))
+            continue;
+        }
 
-      // Figure out if this field is zero bits wide, e.g. {} or [0 x int].
-      bool isZeroSizeField = FieldTy->isSized() &&
-        getTargetData().getTypeSizeInBits(FieldTy) == 0;
-
-      unsigned FieldNo =
-        Info->getLLVMFieldFor(FieldOffsetInBits, CurFieldNo, isZeroSizeField);
-      SetFieldIndex(Field, FieldNo);
-
-      assert((isBitfield(Field) || FieldNo == ~0U ||
-             FieldOffsetInBits == 8*Info->ElementOffsetInBytes[FieldNo]) &&
-             "Wrong LLVM field offset!");
+        // Figure out if this field is zero bits wide, e.g. {} or [0 x int].
+        bool isZeroSizeField = FieldTy->isSized() &&
+          getTargetData().getTypeSizeInBits(FieldTy) == 0;
+
+        unsigned FieldNo =
+          Info->getLLVMFieldFor(FieldOffsetInBits, CurFieldNo, isZeroSizeField);
+        SetFieldIndex(Field, FieldNo);
+
+        assert((isBitfield(Field) || FieldNo == ~0U ||
+                FieldOffsetInBits == 8*Info->ElementOffsetInBytes[FieldNo]) &&
+               "Wrong LLVM field offset!");
+      }
     }
 
   // Put the original gcc struct back the way it was; necessary to prevent the
   // binfo-walking code in cp/class from getting confused.
-  RestoreOriginalFields(type);
+  if (IsStruct)
+    RestoreOriginalFields(type);
 
   const Type *ResultTy = Info->getLLVMType();
   StructTypeInfoMap[type] = Info;
@@ -2210,11 +2304,11 @@
     const_cast<OpaqueType*>(OldTy)->refineAbstractTypeTo(ResultTy);
 
   // Finally, set the name for the type.
-  TheModule->addTypeName(GetTypeName("struct.", orig_type),
-                         GET_TYPE_LLVM(type));
+  TheModule->addTypeName(GetTypeName(IsStruct ? "struct." : "union.",
+                                     orig_type), GET_TYPE_LLVM(type));
 
   // We have finished converting this struct.  See if the is the outer-most
-  // struct being converted by ConvertType.
+  // struct or union being converted by ConvertType.
   ConvertingStruct = OldConvertingStruct;
   if (!ConvertingStruct) {
 
@@ -2236,185 +2330,4 @@
   return GET_TYPE_LLVM(type);
 }
 
-
-/// ConvertUNION - We know that 'type' is a UNION_TYPE or a QUAL_UNION_TYPE:
-/// convert it to an LLVM type.
-const Type *TypeConverter::ConvertUNION(tree type, tree orig_type) {
-  if (const Type *Ty = GET_TYPE_LLVM(type)) {
-    // If we already compiled this type, and if it was not a forward
-    // definition that is now defined, use the old type.
-    if (!isa<OpaqueType>(Ty) || TYPE_SIZE(type) == 0)
-      return Ty;
-  }
-
-  if (TYPE_SIZE(type) == 0) {   // Forward declaraion?
-    const Type *Ty = OpaqueType::get(Context);
-    TheModule->addTypeName(GetTypeName("union.", orig_type), Ty);
-    return TypeDB.setType(type, Ty);
-  }
-
-  // Note that we are compiling a struct now.
-  bool OldConvertingStruct = ConvertingStruct;
-  ConvertingStruct = true;
-
-  // Find the type with the largest aligment, and if we have multiple types with
-  // the same alignment, select one with largest size. If type with max. align
-  // is smaller than other types, then we will add padding later on anyway to
-  // match union size.
-  const TargetData &TD = getTargetData();
-  const Type *UnionTy = 0;
-  tree GccUnionTy = 0;
-  unsigned MaxAlignSize = 0, MaxAlign = 0;
-  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?");
-    // Workaround to get Fortran EQUIVALENCE working.
-    // TODO: Unify record and union logic and handle this optimally.
-    if (getFieldOffsetInBits(Field) != 0) {
-      ConvertingStruct = OldConvertingStruct;
-      return ConvertRECORD(type, orig_type);
-    }
-
-    // Set the field idx to zero for all fields.
-    SetFieldIndex(Field, 0);
-
-    // Skip fields that are known not to be present.
-    if (TREE_CODE(type) == QUAL_UNION_TYPE &&
-        integer_zerop(DECL_QUALIFIER(Field)))
-      continue;
-
-    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)
-      continue;
-#ifdef TARGET_POWERPC
-    // Normally gcc reduces the size of bitfields to the size necessary
-    // to hold the bits, e.g. a 1-bit field becomes QI.  It does not do
-    // this for bool, which is no problem on most targets because
-    // sizeof(bool)==1.  On darwin ppc32, however, sizeof(bool)==4, so
-    // we can have field types bigger than the union type here.  Evade
-    // this by creating an appropriate int type here.
-    //
-    // It's possible this issue is not specific to ppc, but I doubt it.
-
-    if (TREE_CODE(TheGccTy) == BOOLEAN_TYPE &&
-        TYPE_SIZE_UNIT(TheGccTy) &&
-        DECL_SIZE_UNIT(Field) &&
-        TREE_CODE(DECL_SIZE_UNIT(Field)) == INTEGER_CST &&
-        TREE_CODE(TYPE_SIZE_UNIT(TheGccTy)) == INTEGER_CST &&
-        TREE_INT_CST_LOW(TYPE_SIZE_UNIT(TheGccTy)) >
-        TREE_INT_CST_LOW(DECL_SIZE_UNIT(Field))) {
-      bool sign = DECL_UNSIGNED(Field);
-      switch(TREE_INT_CST_LOW(DECL_SIZE_UNIT(Field))) {
-        case 1: TheGccTy = sign ? intQI_type_node : unsigned_intQI_type_node;
-                break;
-        case 2: TheGccTy = sign ? intHI_type_node : unsigned_intHI_type_node;
-                break;
-        case 4: TheGccTy = sign ? intSI_type_node : unsigned_intSI_type_node;
-                break;
-        case 8: TheGccTy = sign ? intDI_type_node : unsigned_intDI_type_node;
-                break;
-        default: assert(0 && "Unexpected field size"); break;
-      }
-    }
-#endif
-    const Type *TheTy = ConvertType(TheGccTy);
-    unsigned Size  = TD.getTypeAllocSize(TheTy);
-    unsigned Align = TD.getABITypeAlignment(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.
-    bool useTheTy;
-    if (UnionTy == 0)
-      useTheTy = true;
-    else if (Align < MaxAlign)
-      useTheTy = false;
-    else if (Align > MaxAlign)
-      useTheTy = true;
-    else if (Size > MaxAlignSize)
-      useTheTy = true;
-    else
-      useTheTy = false;
-
-    if (useTheTy) {
-      UnionTy = TheTy;
-      GccUnionTy = TheGccTy;
-      MaxAlignSize = Size;
-      MaxAlign = Align;
-    }
-
-    // Skip remaining fields if this one is known to be present.
-    if (TREE_CODE(type) == QUAL_UNION_TYPE &&
-        integer_onep(DECL_QUALIFIER(Field)))
-      break;
-  }
-
-  std::vector<const Type*> UnionElts;
-  unsigned EltAlign = 0;
-  unsigned EltSize = 0;
-  if (UnionTy) {            // Not an empty union.
-    EltAlign = TD.getABITypeAlignment(UnionTy);
-    EltSize = TD.getTypeAllocSize(UnionTy);
-    UnionElts.push_back(UnionTy);
-  }
-
-  // If the LLVM struct requires explicit tail padding to be the same size as
-  // the GCC union, insert tail padding now.  This handles cases where the union
-  // has larger alignment than the largest member does, thus requires tail
-  // padding.
-  if (TYPE_SIZE(type) && TREE_CODE(TYPE_SIZE(type)) == INTEGER_CST) {
-    uint64_t GCCTypeSize = getInt64(TYPE_SIZE_UNIT(type), true);
-
-    if (EltSize != GCCTypeSize) {
-      assert(EltSize < GCCTypeSize &&
-             "LLVM type size doesn't match GCC type size!");
-      const Type *PadTy = Type::getInt8Ty(Context);
-      if (GCCTypeSize-EltSize != 1)
-        PadTy = ArrayType::get(PadTy, GCCTypeSize-EltSize);
-      UnionElts.push_back(PadTy);
-    }
-  }
-
-  bool isPacked = 8 * EltAlign > TYPE_ALIGN(type);
-  const Type *ResultTy = StructType::get(Context, UnionElts, isPacked);
-  const OpaqueType *OldTy = cast_or_null<OpaqueType>(GET_TYPE_LLVM(type));
-  TypeDB.setType(type, ResultTy);
-
-  // If there was a forward declaration for this type that is now resolved,
-  // refine anything that used it to the new type.
-  if (OldTy)
-    const_cast<OpaqueType*>(OldTy)->refineAbstractTypeTo(ResultTy);
-
-  // Finally, set the name for the type.
-  TheModule->addTypeName(GetTypeName("union.", orig_type),
-                         GET_TYPE_LLVM(type));
-
-  // We have finished converting this union.  See if the is the outer-most
-  // union being converted by ConvertType.
-  ConvertingStruct = OldConvertingStruct;
-  if (!ConvertingStruct) {
-    // If this is the outer-most level of structness, resolve any pointers
-    // that were deferred.
-    while (!PointersToReresolve.empty()) {
-      if (tree PtrTy = PointersToReresolve.back()) {
-        ConvertType(PtrTy);   // Reresolve this pointer type.
-        assert((PointersToReresolve.empty() ||
-                PointersToReresolve.back() != PtrTy) &&
-               "Something went wrong with pointer resolution!");
-      } else {
-        // Null marker element.
-        PointersToReresolve.pop_back();
-      }
-    }
-  }
-
-  return GET_TYPE_LLVM(type);
-}
-
 /* LLVM LOCAL end (ENTIRE FILE!)  */





More information about the llvm-commits mailing list