[llvm-commits] [llvm-gcc-4.2] r57992 - /llvm-gcc-4.2/trunk/gcc/llvm-convert.cpp

Duncan Sands baldrick at free.fr
Wed Oct 22 11:14:34 PDT 2008


Author: baldrick
Date: Wed Oct 22 13:14:32 2008
New Revision: 57992

URL: http://llvm.org/viewvc/llvm-project?rev=57992&view=rev
Log:
Prevent tramp3d-v4 from crashing llvm-gcc on
x86-64 linux.  It might be better to teach
the struct type convertor to always create an
LLVM field that starts at the same byte as
each gcc field.  However this fix is less
risky, since it only kicks in when llvm-gcc
would otherwise have crashed.

Modified:
    llvm-gcc-4.2/trunk/gcc/llvm-convert.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=57992&r1=57991&r2=57992&view=diff

==============================================================================
--- llvm-gcc-4.2/trunk/gcc/llvm-convert.cpp (original)
+++ llvm-gcc-4.2/trunk/gcc/llvm-convert.cpp Wed Oct 22 13:14:32 2008
@@ -6017,7 +6017,39 @@
       const StructLayout *SL = TD.getStructLayout(cast<StructType>(StructTy));
       BitStart -= SL->getElementOffset(MemberIndex) * 8;
     }
-    
+
+    // Type conversion does not ensure that there is always an LLVM field
+    // starting at the same byte as the gcc field.  Correct for this now.
+    // An example of how this can occur is:
+    //   Field A: offset 0, length 1
+    //   Field B: offset 4, length 4 (4 byte alignment)
+    //   Field C: offset 6
+    // Since field C overlaps field B, we delete field B and replace it with
+    // padding:
+    //   LLVM A: offset 0, length 1
+    //   LLVM B: offset 1, length 5 (1 byte alignment) - padding array
+    //   LLVM C: offset 6
+    // A COMPONENT_REF for gcc field B will get LLVM field B which has
+    // offset 1 not 4.
+    unsigned ByteStart = BitStart/8;
+    if (ByteStart && !isBitfield(FieldDecl)) {
+      const Type *ContainingType =
+        cast<StructType>(StructTy)->getTypeAtIndex(MemberIndex);
+      Value *Offset = ConstantInt::get(TD.getIntPtrType(), ByteStart);
+
+      const ArrayType *ATy = dyn_cast<ArrayType>(ContainingType);
+      if (ATy && ATy->getElementType() == Type::Int8Ty) {
+        // Only known case: the LLVM field is an array of bytes.
+        FieldPtr = Builder.CreateGEP(FieldPtr, Offset);
+      } else {
+        // Do pointer arithmetic.
+        FieldPtr = Builder.CreatePtrToInt(FieldPtr, Offset->getType());
+        FieldPtr = Builder.CreateAdd(FieldPtr, Offset);
+        FieldPtr = Builder.CreateIntToPtr(FieldPtr,
+                                          PointerType::getUnqual(Type::Int8Ty));
+      }
+      BitStart -= ByteStart * 8;
+    }
   } else {
     Value *Offset = Emit(field_offset, 0);
 





More information about the llvm-commits mailing list