[llvm-commits] [dragonegg] r97805 - /dragonegg/trunk/llvm-convert.cpp

Duncan Sands baldrick at free.fr
Fri Mar 5 05:08:38 PST 2010


Author: baldrick
Date: Fri Mar  5 07:08:38 2010
New Revision: 97805

URL: http://llvm.org/viewvc/llvm-project?rev=97805&view=rev
Log:
Clean up and simplify the code for handling COMPONENT_REF.  The simplifications
occur because when a GCC field maps directly to an LLVM field, the bit-offset
between the start of the LLVM field and the start of the GCC field is guaranteed
to be less than 8 (one octet).

Modified:
    dragonegg/trunk/llvm-convert.cpp

Modified: dragonegg/trunk/llvm-convert.cpp
URL: http://llvm.org/viewvc/llvm-project/dragonegg/trunk/llvm-convert.cpp?rev=97805&r1=97804&r2=97805&view=diff
==============================================================================
--- dragonegg/trunk/llvm-convert.cpp (original)
+++ dragonegg/trunk/llvm-convert.cpp Fri Mar  5 07:08:38 2010
@@ -5311,10 +5311,6 @@
           TREE_CODE(DECL_CONTEXT(FieldDecl)) == UNION_TYPE  ||
           TREE_CODE(DECL_CONTEXT(FieldDecl)) == QUAL_UNION_TYPE));
 
-  // Ensure that the struct type has been converted, so that the fielddecls
-  // are laid out.  Note that we convert to the context of the Field, not to the
-  // type of Operand #0, because GCC doesn't always have the field match up with
-  // operand #0's type.
   const Type *StructTy = ConvertType(DECL_CONTEXT(FieldDecl));
 
   assert((!StructAddrLV.isBitfield() ||
@@ -5332,45 +5328,12 @@
   // If the GCC field directly corresponds to an LLVM field, handle it.
   unsigned MemberIndex = GetFieldIndex(FieldDecl, StructTy);
   if (MemberIndex < INT_MAX) {
-    BitStart = getFieldOffsetInBits(TREE_OPERAND(exp, 1));
     assert(!TREE_OPERAND(exp, 2) && "Constant not gimple min invariant?");
-
-    // If the LLVM struct has zero field, don't try to index into it, just use
-    // the current pointer.
-    FieldPtr = StructAddrLV.Ptr;
-    if (StructTy->getNumContainedTypes() != 0) {
-      assert(MemberIndex < StructTy->getNumContainedTypes() &&
-             "Field Idx out of range!");
-      FieldPtr = Builder.CreateStructGEP(FieldPtr, MemberIndex);
-    }
-
-    // Now that we did an offset from the start of the struct, subtract off
-    // the offset from BitStart.
-    if (MemberIndex) {
-      const StructLayout *SL = TD.getStructLayout(cast<StructType>(StructTy));
-      unsigned Offset = SL->getElementOffset(MemberIndex);
-      BitStart -= Offset * 8;
-
-      // If the base is known to be 8-byte aligned, and we're adding a 4-byte
-      // offset, the field is known to be 4-byte aligned.
-      LVAlign = MinAlign(LVAlign, Offset);
-    }
-
-    // There is debate about whether this is really safe or not, be conservative
-    // in the meantime.
-#if 0
-    // If this field is at a constant offset, if the LLVM pointer really points
-    // to it, then we know that the pointer is at least as aligned as the field
-    // is required to be.  Try to round up our alignment info.
-    if (BitStart == 0 && // llvm pointer points to it.
-        !isBitfield(FieldDecl) &&  // bitfield computation might offset pointer.
-        DECL_ALIGN(FieldDecl))
-      LVAlign = std::max(LVAlign, unsigned(DECL_ALIGN(FieldDecl)) / 8);
-#endif
-
-    // If the FIELD_DECL has an annotate attribute on it, emit it.
-    if (lookup_attribute("annotate", DECL_ATTRIBUTES(FieldDecl)))
-      FieldPtr = EmitFieldAnnotation(FieldPtr, FieldDecl);
+    // Get a pointer to the byte in which the GCC field starts.
+    FieldPtr = Builder.CreateStructGEP(StructAddrLV.Ptr, MemberIndex);
+    // Within that byte, the bit at which the GCC field starts.
+    BitStart = TREE_INT_CST_LOW(DECL_FIELD_BIT_OFFSET(TREE_OPERAND(exp, 1)));
+    BitStart &= 7;
   } else {
     // Offset will hold the field offset in octets.
     Value *Offset;
@@ -5396,115 +5359,123 @@
 
     // Here BitStart gives the offset of the field in bits from Offset.
     BitStart = getInt64(DECL_FIELD_BIT_OFFSET(FieldDecl), true);
+
     // Incorporate as much of it as possible into the pointer computation.
-    unsigned ByteOffset = BitStart/8;
+    unsigned ByteOffset = BitStart / 8;
     if (ByteOffset > 0) {
       Offset = Builder.CreateAdd(Offset,
         ConstantInt::get(Offset->getType(), ByteOffset));
       BitStart -= ByteOffset*8;
-      // If the base is known to be 8-byte aligned, and we're adding a 4-byte
-      // offset, the field is known to be 4-byte aligned.
-      LVAlign = MinAlign(LVAlign, ByteOffset);
-    }
-
-    Value *Ptr = Builder.CreatePtrToInt(StructAddrLV.Ptr, Offset->getType());
-    Ptr = Builder.CreateAdd(Ptr, Offset);
-    FieldPtr = Builder.CreateIntToPtr(Ptr, FieldTy->getPointerTo());
-  }
-
-  if (isBitfield(FieldDecl)) {
-    // If this is a bitfield, the declared type must be an integral type.
-    assert(FieldTy->isIntegerTy() && "Invalid bitfield");
-
-    assert(DECL_SIZE(FieldDecl) &&
-           TREE_CODE(DECL_SIZE(FieldDecl)) == INTEGER_CST &&
-           "Variable sized bitfield?");
-    unsigned BitfieldSize = TREE_INT_CST_LOW(DECL_SIZE(FieldDecl));
-
-    const Type *LLVMFieldTy =
-      cast<PointerType>(FieldPtr->getType())->getElementType();
-
-    // If the LLVM notion of the field type contains the entire bitfield being
-    // accessed, use the LLVM type.  This avoids pointer casts and other bad
-    // things that are difficult to clean up later.  This occurs in cases like
-    // "struct X{ unsigned long long x:50; unsigned y:2; }" when accessing y.
-    // We want to access the field as a ulong, not as a uint with an offset.
-    if (LLVMFieldTy->isIntegerTy() &&
-        LLVMFieldTy->getPrimitiveSizeInBits() >= BitStart + BitfieldSize &&
-        LLVMFieldTy->getPrimitiveSizeInBits() ==
-        TD.getTypeAllocSizeInBits(LLVMFieldTy))
-      FieldTy = LLVMFieldTy;
-    else
-      // If the field result type T is a bool or some other curiously sized
-      // integer type, then not all bits may be accessible by advancing a T*
-      // and loading through it.  For example, if the result type is i1 then
-      // only the first bit in each byte would be loaded.  Even if T is byte
-      // sized like an i24 there may be trouble: incrementing a T* will move
-      // the position by 32 bits not 24, leaving the upper 8 of those 32 bits
-      // inaccessible.  Avoid this by rounding up the size appropriately.
-      FieldTy = IntegerType::get(Context, TD.getTypeAllocSizeInBits(FieldTy));
-
-    assert(FieldTy->getPrimitiveSizeInBits() ==
-           TD.getTypeAllocSizeInBits(FieldTy) && "Field type not sequential!");
+    }
 
-    // If this is a bitfield, the field may span multiple fields in the LLVM
-    // type.  As such, cast the pointer to be a pointer to the declared type.
+    const Type *BytePtrTy = Type::getInt8PtrTy(Context);
+    FieldPtr = Builder.CreateBitCast(StructAddrLV.Ptr, BytePtrTy);
+    FieldPtr = Builder.CreateInBoundsGEP(FieldPtr, Offset);
     FieldPtr = Builder.CreateBitCast(FieldPtr, FieldTy->getPointerTo());
+  }
 
-    unsigned LLVMValueBitSize = FieldTy->getPrimitiveSizeInBits();
-    // Finally, because bitfields can span LLVM fields, and because the start
-    // of the first LLVM field (where FieldPtr currently points) may be up to
-    // 63 bits away from the start of the bitfield), it is possible that
-    // *FieldPtr doesn't contain any of the bits for this bitfield. If needed,
-    // adjust FieldPtr so that it is close enough to the bitfield that
-    // *FieldPtr contains the first needed bit.  Be careful to make sure that
-    // the pointer remains appropriately aligned.
-    if (BitStart > LLVMValueBitSize) {
-      // In this case, we know that the alignment of the field is less than
-      // the size of the field.  To get the pointer close enough, add some
-      // number of alignment units to the pointer.
-      unsigned ByteAlignment = TD.getABITypeAlignment(FieldTy);
-      // It is possible that an individual field is Packed. This information is
-      // not reflected in FieldTy. Check DECL_PACKED here.
-      if (DECL_PACKED(FieldDecl))
-        ByteAlignment = 1;
-      assert(ByteAlignment*8 <= LLVMValueBitSize && "Unknown overlap case!");
-      unsigned NumAlignmentUnits = BitStart/(ByteAlignment*8);
-      assert(NumAlignmentUnits && "Not adjusting pointer?");
-
-      // Compute the byte offset, and add it to the pointer.
-      unsigned ByteOffset = NumAlignmentUnits*ByteAlignment;
-      LVAlign = MinAlign(LVAlign, ByteOffset);
-
-      Constant *Offset = ConstantInt::get(TD.getIntPtrType(Context), ByteOffset);
-      FieldPtr = Builder.CreatePtrToInt(FieldPtr, Offset->getType());
-      FieldPtr = Builder.CreateAdd(FieldPtr, Offset);
-      FieldPtr = Builder.CreateIntToPtr(FieldPtr, FieldTy->getPointerTo());
-
-      // Adjust bitstart to account for the pointer movement.
-      BitStart -= ByteOffset*8;
+  assert(BitStart < 8 && "Bit offset not properly incorporated in the pointer");
 
-      // Check that this worked.  Note that the bitfield may extend beyond
-      // the end of *FieldPtr, for example because BitfieldSize is the same
-      // as LLVMValueBitSize but BitStart > 0.
-      assert(BitStart < LLVMValueBitSize &&
-             BitStart+BitfieldSize < 2*LLVMValueBitSize &&
-             "Couldn't get bitfield into value!");
-    }
+  // The alignment is given by DECL_ALIGN.  Be conservative and don't assume
+  // that the field is properly aligned even if the type is not.
+  LVAlign = MinAlign(LVAlign, DECL_ALIGN(FieldDecl) / 8);
+
+  // If the FIELD_DECL has an annotate attribute on it, emit it.
+  if (lookup_attribute("annotate", DECL_ATTRIBUTES(FieldDecl)))
+    FieldPtr = EmitFieldAnnotation(FieldPtr, FieldDecl);
 
-    // Okay, everything is good.  Return this as a bitfield if we can't
-    // return it as a normal l-value. (e.g. "struct X { int X : 32 };" ).
-    if (BitfieldSize != LLVMValueBitSize || BitStart != 0)
-      return LValue(FieldPtr, LVAlign, BitStart, BitfieldSize);
-    
-  } else {
+  if (!isBitfield(FieldDecl)) {
+    assert(BitStart == 0 && "Not a bitfield but not at a byte offset!");
     // Make sure we return a pointer to the right type.
     const Type *EltTy = ConvertType(TREE_TYPE(exp));
     FieldPtr = Builder.CreateBitCast(FieldPtr, EltTy->getPointerTo());
+    return LValue(FieldPtr, LVAlign);
   }
 
-  assert(BitStart == 0 &&
-         "It's a bitfield reference or we didn't get to the field!");
+  // If this is a bitfield, the declared type must be an integral type.
+  assert(FieldTy->isIntegerTy() && "Invalid bitfield");
+
+  assert(DECL_SIZE(FieldDecl) &&
+         TREE_CODE(DECL_SIZE(FieldDecl)) == INTEGER_CST &&
+         "Variable sized bitfield?");
+  unsigned BitfieldSize = TREE_INT_CST_LOW(DECL_SIZE(FieldDecl));
+
+  const Type *LLVMFieldTy =
+    cast<PointerType>(FieldPtr->getType())->getElementType();
+
+  // If the LLVM notion of the field type contains the entire bitfield being
+  // accessed, use the LLVM type.  This avoids pointer casts and other bad
+  // things that are difficult to clean up later.  This occurs in cases like
+  // "struct X{ unsigned long long x:50; unsigned y:2; }" when accessing y.
+  // We want to access the field as a ulong, not as a uint with an offset.
+  if (LLVMFieldTy->isIntegerTy() &&
+      LLVMFieldTy->getPrimitiveSizeInBits() >= BitStart + BitfieldSize &&
+      LLVMFieldTy->getPrimitiveSizeInBits() ==
+      TD.getTypeAllocSizeInBits(LLVMFieldTy))
+    FieldTy = LLVMFieldTy;
+  else
+    // If the field result type T is a bool or some other curiously sized
+    // integer type, then not all bits may be accessible by advancing a T*
+    // and loading through it.  For example, if the result type is i1 then
+    // only the first bit in each byte would be loaded.  Even if T is byte
+    // sized like an i24 there may be trouble: incrementing a T* will move
+    // the position by 32 bits not 24, leaving the upper 8 of those 32 bits
+    // inaccessible.  Avoid this by rounding up the size appropriately.
+    FieldTy = IntegerType::get(Context, TD.getTypeAllocSizeInBits(FieldTy));
+
+  assert(FieldTy->getPrimitiveSizeInBits() ==
+         TD.getTypeAllocSizeInBits(FieldTy) && "Field type not sequential!");
+
+  // If this is a bitfield, the field may span multiple fields in the LLVM
+  // type.  As such, cast the pointer to be a pointer to the declared type.
+  FieldPtr = Builder.CreateBitCast(FieldPtr, FieldTy->getPointerTo());
+
+  unsigned LLVMValueBitSize = FieldTy->getPrimitiveSizeInBits();
+  // Finally, because bitfields can span LLVM fields, and because the start
+  // of the first LLVM field (where FieldPtr currently points) may be up to
+  // 63 bits away from the start of the bitfield), it is possible that
+  // *FieldPtr doesn't contain any of the bits for this bitfield. If needed,
+  // adjust FieldPtr so that it is close enough to the bitfield that
+  // *FieldPtr contains the first needed bit.  Be careful to make sure that
+  // the pointer remains appropriately aligned.
+  if (BitStart > LLVMValueBitSize) {
+    // In this case, we know that the alignment of the field is less than
+    // the size of the field.  To get the pointer close enough, add some
+    // number of alignment units to the pointer.
+    unsigned ByteAlignment = TD.getABITypeAlignment(FieldTy);
+    // It is possible that an individual field is Packed. This information is
+    // not reflected in FieldTy. Check DECL_PACKED here.
+    if (DECL_PACKED(FieldDecl))
+      ByteAlignment = 1;
+    assert(ByteAlignment*8 <= LLVMValueBitSize && "Unknown overlap case!");
+    unsigned NumAlignmentUnits = BitStart/(ByteAlignment*8);
+    assert(NumAlignmentUnits && "Not adjusting pointer?");
+
+    // Compute the byte offset, and add it to the pointer.
+    unsigned ByteOffset = NumAlignmentUnits*ByteAlignment;
+    LVAlign = MinAlign(LVAlign, ByteOffset);
+
+    Constant *Offset = ConstantInt::get(TD.getIntPtrType(Context), ByteOffset);
+    FieldPtr = Builder.CreatePtrToInt(FieldPtr, Offset->getType());
+    FieldPtr = Builder.CreateAdd(FieldPtr, Offset);
+    FieldPtr = Builder.CreateIntToPtr(FieldPtr, FieldTy->getPointerTo());
+
+    // Adjust bitstart to account for the pointer movement.
+    BitStart -= ByteOffset*8;
+
+    // Check that this worked.  Note that the bitfield may extend beyond
+    // the end of *FieldPtr, for example because BitfieldSize is the same
+    // as LLVMValueBitSize but BitStart > 0.
+    assert(BitStart < LLVMValueBitSize &&
+           BitStart+BitfieldSize < 2*LLVMValueBitSize &&
+           "Couldn't get bitfield into value!");
+  }
+
+  // Okay, everything is good.  Return this as a bitfield if we can't
+  // return it as a normal l-value. (e.g. "struct X { int X : 32 };" ).
+  if (BitfieldSize != LLVMValueBitSize || BitStart != 0)
+    return LValue(FieldPtr, LVAlign, BitStart, BitfieldSize);
+
   return LValue(FieldPtr, LVAlign);
 }
 
@@ -8592,11 +8563,8 @@
 Constant *TreeConstantToLLVM::EmitLV_COMPONENT_REF(tree exp) {
   Constant *StructAddrLV = EmitLV(TREE_OPERAND(exp, 0));
 
-  // Ensure that the struct type has been converted, so that the fielddecls
-  // are laid out.
-  const Type *StructTy = ConvertType(TREE_TYPE(TREE_OPERAND(exp, 0)));
-
   tree FieldDecl = TREE_OPERAND(exp, 1);
+  const Type *StructTy = ConvertType(DECL_CONTEXT(FieldDecl));
 
   StructAddrLV = TheFolder->CreateBitCast(StructAddrLV,
                                           StructTy->getPointerTo());
@@ -8606,27 +8574,19 @@
   // struct, in bits.  For bitfields this may be on a non-byte boundary.
   unsigned BitStart;
   Constant *FieldPtr;
-  const TargetData &TD = getTargetData();
 
   // If the GCC field directly corresponds to an LLVM field, handle it.
   unsigned MemberIndex = GetFieldIndex(FieldDecl, StructTy);
   if (MemberIndex < INT_MAX) {
-    BitStart = getFieldOffsetInBits(TREE_OPERAND(exp, 1));
-
+    // Get a pointer to the byte in which the GCC field starts.
     Constant *Ops[] = {
-      StructAddrLV,
       Constant::getNullValue(Type::getInt32Ty(Context)),
       ConstantInt::get(Type::getInt32Ty(Context), MemberIndex)
     };
-    FieldPtr = TheFolder->CreateInBoundsGetElementPtr(StructAddrLV, Ops+1, 2);
-
-    // Now that we did an offset from the start of the struct, subtract off
-    // the offset from BitStart.
-    if (MemberIndex) {
-      const StructLayout *SL = TD.getStructLayout(cast<StructType>(StructTy));
-      BitStart -= SL->getElementOffset(MemberIndex) * 8;
-    }
-
+    FieldPtr = TheFolder->CreateInBoundsGetElementPtr(StructAddrLV, Ops, 2);
+    // Within that byte, the bit at which the GCC field starts.
+    BitStart = TREE_INT_CST_LOW(DECL_FIELD_BIT_OFFSET(TREE_OPERAND(exp, 1)));
+    BitStart &= 7;
   } else {
     // Offset will hold the field offset in octets.
     Constant *Offset;
@@ -8663,14 +8623,15 @@
       BitStart -= ByteOffset*8;
     }
 
-    Constant *Ptr = TheFolder->CreatePtrToInt(StructAddrLV, Offset->getType());
-    Ptr = TheFolder->CreateAdd(Ptr, Offset);
-    FieldPtr = TheFolder->CreateIntToPtr(Ptr, FieldTy->getPointerTo());
+    const Type *BytePtrTy = Type::getInt8PtrTy(Context);
+    FieldPtr = TheFolder->CreateBitCast(StructAddrLV, BytePtrTy);
+    FieldPtr = TheFolder->CreateInBoundsGetElementPtr(FieldPtr, &Offset, 1);
+    FieldPtr = TheFolder->CreateBitCast(FieldPtr, FieldTy->getPointerTo());
   }
 
-  // Make sure we return a result of the right type.
-  if (FieldTy->getPointerTo() != FieldPtr->getType())
-    FieldPtr = TheFolder->CreateBitCast(FieldPtr, FieldTy->getPointerTo());
+  // Make sure we return a pointer to the right type.
+  const Type *EltTy = ConvertType(TREE_TYPE(exp));
+  FieldPtr = TheFolder->CreateBitCast(FieldPtr, EltTy->getPointerTo());
 
   assert(BitStart == 0 &&
          "It's a bitfield reference or we didn't get to the field!");





More information about the llvm-commits mailing list