<html><head></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space; "><br><div><div>On May 3, 2010, at 9:48 PM, Chris Lattner wrote:</div><br class="Apple-interchange-newline"><blockquote type="cite"><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space; "><br><div><div>On May 3, 2010, at 5:05 PM, Stuart Hastings wrote:</div><br class="Apple-interchange-newline"><blockquote type="cite"><div>Author: stuart<br>Date: Mon May  3 19:05:41 2010<br>New Revision: 102979<br><br>URL: <a href="http://llvm.org/viewvc/llvm-project?rev=102979&view=rev">http://llvm.org/viewvc/llvm-project?rev=102979&view=rev</a><br>Log:<br>When referencing a field, void touching memory outside of the enclosing struct.  Radar 7349042.<br></div></blockquote><div><br></div>Does this fix <a href="http://llvm.org/bugs/show_bug.cgi?id=2394">http://llvm.org/bugs/show_bug.cgi?id=2394</a> ?</div></div></blockquote><div><br></div>Yes.</div><div><br></div><div><blockquote type="cite"><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space; "><div> Does it help with <a href="http://llvm.org/bugs/show_bug.cgi?id=5995">http://llvm.org/bugs/show_bug.cgi?id=5995</a> / (aka <span class="Apple-style-span" style="font-family: monospace, sans-serif; white-space: pre-wrap; -webkit-border-horizontal-spacing: 1px; -webkit-border-vertical-spacing: 1px; "><a href="rdar://7885836">rdar://7885836</a>)?</span></div></div></blockquote><div><br></div>Sorry, no.</div><div><br></div><div>stuart</div><div><br><blockquote type="cite"><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space; "><div>-Chris</div><div><br><blockquote type="cite"><div><br>Modified:<br>    llvm-gcc-4.2/trunk/gcc/llvm-convert.cpp<br><br>Modified: llvm-gcc-4.2/trunk/gcc/llvm-convert.cpp<br>URL: <a href="http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/gcc/llvm-convert.cpp?rev=102979&r1=102978&r2=102979&view=diff">http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/gcc/llvm-convert.cpp?rev=102979&r1=102978&r2=102979&view=diff</a><br>==============================================================================<br>--- llvm-gcc-4.2/trunk/gcc/llvm-convert.cpp (original)<br>+++ llvm-gcc-4.2/trunk/gcc/llvm-convert.cpp Mon May  3 19:05:41 2010<br>@@ -7141,6 +7141,7 @@<br>   // struct, in bits.  For bitfields this may be on a non-byte boundary.<br>   unsigned BitStart = getComponentRefOffsetInBits(exp);<br>   Value *FieldPtr;<br>+  unsigned ByteOffset = 0;<br><br>   tree field_offset = component_ref_field_offset (exp);<br>   // If this is a normal field at a fixed offset from the start, handle it.<br>@@ -7160,12 +7161,12 @@<br>     // the offset from BitStart.<br>     if (MemberIndex) {<br>       const StructLayout *SL = TD.getStructLayout(cast<StructType>(StructTy));<br>-      unsigned Offset = SL->getElementOffset(MemberIndex);<br>-      BitStart -= Offset * 8;<br>+      ByteOffset = SL->getElementOffset(MemberIndex);<br>+      BitStart -= ByteOffset * 8;<br><br>       // If the base is known to be 8-byte aligned, and we're adding a 4-byte<br>       // offset, the field is known to be 4-byte aligned.<br>-      LVAlign = MinAlign(LVAlign, Offset);<br>+      LVAlign = MinAlign(LVAlign, ByteOffset);<br>     }<br><br>     // There is debate about whether this is really safe or not, be conservative<br>@@ -7197,7 +7198,7 @@<br>     }<br>     // Here BitStart gives the offset of the field in bits from field_offset.<br>     // Incorporate as much of it as possible into the pointer computation.<br>-    unsigned ByteOffset = BitStart/8;<br>+    ByteOffset = BitStart/8;<br>     if (ByteOffset > 0) {<br>       Offset = Builder.CreateAdd(Offset,<br>         ConstantInt::get(Offset->getType(), ByteOffset));<br>@@ -7231,15 +7232,38 @@<br>     const Type *LLVMFieldTy =<br>       cast<PointerType>(FieldPtr->getType())->getElementType();<br><br>-    // If the LLVM notion of the field type contains the entire bitfield being<br>-    // accessed, use the LLVM type.  This avoids pointer casts and other bad<br>-    // things that are difficult to clean up later.  This occurs in cases like<br>-    // "struct X{ unsigned long long x:50; unsigned y:2; }" when accessing y.<br>-    // We want to access the field as a ulong, not as a uint with an offset.<br>-    if (LLVMFieldTy->isIntegerTy() &&<br>-        LLVMFieldTy->getPrimitiveSizeInBits() >= BitStart + BitfieldSize &&<br>-        LLVMFieldTy->getPrimitiveSizeInBits() ==<br>-        TD.getTypeAllocSizeInBits(LLVMFieldTy))<br>+    // 'piecemeal' will be true if the fetch-type we wish to use will<br>+    // reference memory outside of the struct.  (That's not good.)<br>+    // Note this check is too simplistic: if this field is part of a<br>+    // struct within another struct, it's probably O.K. to fetch data<br>+    // outside of the bitfield, unless the inadvertently-referenced<br>+    // data is volatile.  But we're too lazy to check for that; choose<br>+    // the slow-but-conservative-and-always-correct path.<br>+    tree gccContext = DECL_FIELD_CONTEXT(FieldDecl);<br>+    tree gccSize = TYPE_SIZE(gccContext);<br>+    unsigned int gccStructSize = TREE_INT_CST_LOW(gccSize);<br>+    // piecemeal == true means we fetch the bitfield in pieces and<br>+    // reassemble in a register.<br>+    bool piecemeal = false;<br>+<br>+    if (ByteOffset * 8 + TD.getTypeAllocSizeInBits(FieldTy) > gccStructSize) {<br>+      // If the LLVM notion of the type would reference memory outside<br>+      // of the enclosing struct, punt and fetch the bitfield<br>+      // piecemeal.  Round the bitfield size up to the nearest byte;<br>+      // use existing size if it's already a multiple of 8:<br>+      unsigned int byteAlignedBitfieldSize = (BitfieldSize % 8) ?<br>+        ((BitfieldSize / 8) + 1) * 8 : BitfieldSize;<br>+      FieldTy = Type::getIntNTy(Context, byteAlignedBitfieldSize);<br>+      piecemeal = true;<br>+    } else if (LLVMFieldTy->isIntegerTy() &&<br>+             LLVMFieldTy->getPrimitiveSizeInBits() >= BitStart + BitfieldSize &&<br>+             LLVMFieldTy->getPrimitiveSizeInBits() ==<br>+             TD.getTypeAllocSizeInBits(LLVMFieldTy))<br>+      // If the LLVM notion of the field type contains the entire bitfield being<br>+      // accessed, use the LLVM type.  This avoids pointer casts and other bad<br>+      // things that are difficult to clean up later.  This occurs in cases like<br>+      // "struct X{ unsigned long long x:50; unsigned y:2; }" when accessing y.<br>+      // We want to access the field as a ulong, not as a uint with an offset.<br>       FieldTy = LLVMFieldTy;<br>     else<br>       // If the field result type T is a bool or some other curiously sized<br>@@ -7251,8 +7275,9 @@<br>       // inaccessible.  Avoid this by rounding up the size appropriately.<br>       FieldTy = IntegerType::get(Context, TD.getTypeAllocSizeInBits(FieldTy));<br><br>-    assert(FieldTy->getPrimitiveSizeInBits() ==<br>-           TD.getTypeAllocSizeInBits(FieldTy) && "Field type not sequential!");<br>+    assert((piecemeal || (FieldTy->getPrimitiveSizeInBits() ==<br>+                          TD.getTypeAllocSizeInBits(FieldTy))) &&<br>+           "Field type not sequential!");<br><br>     // If this is a bitfield, the field may span multiple fields in the LLVM<br>     // type.  As such, cast the pointer to be a pointer to the declared type.<br><br><br>_______________________________________________<br>llvm-commits mailing list<br><a href="mailto:llvm-commits@cs.uiuc.edu">llvm-commits@cs.uiuc.edu</a><br><a href="http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits">http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits</a><br></div></blockquote></div><br></div></blockquote></div><br></body></html>