[llvm-branch-commits] [llvm-gcc-branch] r103054 - /llvm-gcc-4.2/branches/Apple/Morbo/gcc/llvm-convert.cpp
Bill Wendling
isanbard at gmail.com
Tue May 4 14:41:52 PDT 2010
Author: void
Date: Tue May 4 16:41:52 2010
New Revision: 103054
URL: http://llvm.org/viewvc/llvm-project?rev=103054&view=rev
Log:
$ svn merge -c 102979 https://llvm.org/svn/llvm-project/llvm-gcc-4.2/trunk
--- Merging r102979 into '.':
U gcc/llvm-convert.cpp
Modified:
llvm-gcc-4.2/branches/Apple/Morbo/gcc/llvm-convert.cpp
Modified: llvm-gcc-4.2/branches/Apple/Morbo/gcc/llvm-convert.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/branches/Apple/Morbo/gcc/llvm-convert.cpp?rev=103054&r1=103053&r2=103054&view=diff
==============================================================================
--- llvm-gcc-4.2/branches/Apple/Morbo/gcc/llvm-convert.cpp (original)
+++ llvm-gcc-4.2/branches/Apple/Morbo/gcc/llvm-convert.cpp Tue May 4 16:41:52 2010
@@ -7077,6 +7077,7 @@
// struct, in bits. For bitfields this may be on a non-byte boundary.
unsigned BitStart = getComponentRefOffsetInBits(exp);
Value *FieldPtr;
+ unsigned ByteOffset = 0;
tree field_offset = component_ref_field_offset (exp);
// If this is a normal field at a fixed offset from the start, handle it.
@@ -7096,12 +7097,12 @@
// the offset from BitStart.
if (MemberIndex) {
const StructLayout *SL = TD.getStructLayout(cast<StructType>(StructTy));
- unsigned Offset = SL->getElementOffset(MemberIndex);
- BitStart -= Offset * 8;
+ ByteOffset = SL->getElementOffset(MemberIndex);
+ 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, Offset);
+ LVAlign = MinAlign(LVAlign, ByteOffset);
}
// There is debate about whether this is really safe or not, be conservative
@@ -7133,7 +7134,7 @@
}
// Here BitStart gives the offset of the field in bits from field_offset.
// Incorporate as much of it as possible into the pointer computation.
- unsigned ByteOffset = BitStart/8;
+ ByteOffset = BitStart/8;
if (ByteOffset > 0) {
Offset = Builder.CreateAdd(Offset,
ConstantInt::get(Offset->getType(), ByteOffset));
@@ -7167,15 +7168,38 @@
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))
+ // 'piecemeal' will be true if the fetch-type we wish to use will
+ // reference memory outside of the struct. (That's not good.)
+ // Note this check is too simplistic: if this field is part of a
+ // struct within another struct, it's probably O.K. to fetch data
+ // outside of the bitfield, unless the inadvertently-referenced
+ // data is volatile. But we're too lazy to check for that; choose
+ // the slow-but-conservative-and-always-correct path.
+ tree gccContext = DECL_FIELD_CONTEXT(FieldDecl);
+ tree gccSize = TYPE_SIZE(gccContext);
+ unsigned int gccStructSize = TREE_INT_CST_LOW(gccSize);
+ // piecemeal == true means we fetch the bitfield in pieces and
+ // reassemble in a register.
+ bool piecemeal = false;
+
+ if (ByteOffset * 8 + TD.getTypeAllocSizeInBits(FieldTy) > gccStructSize) {
+ // If the LLVM notion of the type would reference memory outside
+ // of the enclosing struct, punt and fetch the bitfield
+ // piecemeal. Round the bitfield size up to the nearest byte;
+ // use existing size if it's already a multiple of 8:
+ unsigned int byteAlignedBitfieldSize = (BitfieldSize % 8) ?
+ ((BitfieldSize / 8) + 1) * 8 : BitfieldSize;
+ FieldTy = Type::getIntNTy(Context, byteAlignedBitfieldSize);
+ piecemeal = true;
+ } else if (LLVMFieldTy->isIntegerTy() &&
+ LLVMFieldTy->getPrimitiveSizeInBits() >= BitStart + BitfieldSize &&
+ LLVMFieldTy->getPrimitiveSizeInBits() ==
+ TD.getTypeAllocSizeInBits(LLVMFieldTy))
+ // 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.
FieldTy = LLVMFieldTy;
else
// If the field result type T is a bool or some other curiously sized
@@ -7187,8 +7211,9 @@
// 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!");
+ assert((piecemeal || (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.
More information about the llvm-branch-commits
mailing list