The third operand of a COMPONENT_REF represents the byte offset of
the field; it is accessed using component_ref_field_offset.  Most of
the time you can get away with extracting the offset from the type,
using DECL_FIELD_OFFSET, which is what is done currently, but this
can fail if DECL_FIELD_OFFSET contains a PLACEHOLDER_EXPR for example.
The NON_LVALUE_EXPR Ada testcase also tests this one.
Index: gcc.llvm.master/gcc/llvm-convert.cpp
===================================================================
--- gcc.llvm.master.orig/gcc/llvm-convert.cpp	2007-03-02 15:19:49.000000000 +0100
+++ gcc.llvm.master/gcc/llvm-convert.cpp	2007-03-02 15:19:51.000000000 +0100
@@ -4588,6 +4588,20 @@
   return Result;
 }
 
+/// getComponentRefOffsetInBits - Return the offset (in bits) of the field
+/// referenced in a COMPONENT_REF exp.
+static unsigned getComponentRefOffsetInBits(tree exp) {
+  assert(TREE_CODE(exp) == COMPONENT_REF && "not a COMPONENT_REF!");
+  tree field = TREE_OPERAND(exp, 1);
+  assert(TREE_CODE(field) == FIELD_DECL && "not a FIELD_DECL!");
+  tree field_offset = component_ref_field_offset (exp);
+  assert(DECL_FIELD_BIT_OFFSET(field) && field_offset);
+  unsigned Result = TREE_INT_CST_LOW(DECL_FIELD_BIT_OFFSET(field));
+  if (TREE_CODE(field_offset) == INTEGER_CST)
+    Result += TREE_INT_CST_LOW(field_offset)*8;
+  return Result;
+}
+
 LValue TreeToLLVM::EmitLV_COMPONENT_REF(tree exp) {
   LValue StructAddrLV = EmitLV(TREE_OPERAND(exp, 0));
   tree FieldDecl = TREE_OPERAND(exp, 1);
@@ -4610,11 +4624,12 @@
   
   // BitStart - This is the actual offset of the field from the start of the
   // struct, in bits.  For bitfields this may be on a non-byte boundary.
-  unsigned BitStart = getFieldOffsetInBits(FieldDecl);
+  unsigned BitStart = getComponentRefOffsetInBits(exp);
   Value *FieldPtr;
   
+  tree field_offset = component_ref_field_offset (exp);
   // If this is a normal field at a fixed offset from the start, handle it.
-  if (TREE_CODE(DECL_FIELD_OFFSET(FieldDecl)) == INTEGER_CST) {
+  if (TREE_CODE(field_offset) == INTEGER_CST) {
     assert(DECL_LLVM_SET_P(FieldDecl) && "Struct not laid out for LLVM?");
     ConstantInt *CI = cast<ConstantInt>(DECL_LLVM(FieldDecl));
     uint32_t MemberIndex = CI->getZExtValue();
@@ -4638,7 +4653,7 @@
     }
     
   } else {
-    Value *Offset = Emit(DECL_FIELD_OFFSET(FieldDecl), 0);
+    Value *Offset = Emit(field_offset, 0);
     Value *Ptr = CastToType(Instruction::PtrToInt, StructAddrLV.Ptr, 
                             Offset->getType());
     Ptr = BinaryOperator::createAdd(Ptr, Offset, "tmp", CurBB);
@@ -5662,13 +5677,14 @@
   
   // BitStart - This is the actual offset of the field from the start of the
   // struct, in bits.  For bitfields this may be on a non-byte boundary.
-  unsigned BitStart = getFieldOffsetInBits(FieldDecl);
+  unsigned BitStart = getComponentRefOffsetInBits(exp);
   unsigned BitSize  = 0;
   Constant *FieldPtr;
   const TargetData &TD = getTargetData();
-  
+
+  tree field_offset = component_ref_field_offset (exp);
   // If this is a normal field at a fixed offset from the start, handle it.
-  if (TREE_CODE(DECL_FIELD_OFFSET(FieldDecl)) == INTEGER_CST) {
+  if (TREE_CODE(field_offset) == INTEGER_CST) {
     assert(DECL_LLVM_SET_P(FieldDecl) && "Struct not laid out for LLVM?");
     ConstantInt *CI = cast<ConstantInt>(DECL_LLVM(FieldDecl));
     uint64_t MemberIndex = CI->getZExtValue();
@@ -5688,18 +5704,18 @@
       }
     } else {
       // We were unable to make a nice offset, emit an ugly one.
-      Constant *Offset = Convert(DECL_FIELD_OFFSET(FieldDecl));
+      Constant *Offset = Convert(field_offset);
       FieldPtr = ConstantExpr::getPtrToInt(StructAddrLV, Offset->getType());
       FieldPtr = ConstantExpr::getAdd(FieldPtr, Offset);
       FieldPtr = ConstantExpr::getIntToPtr(FieldPtr, PointerType::get(FieldTy));
       
       // Do horrible pointer arithmetic to get the address of the field.
-      unsigned ByteOffset = TREE_INT_CST_LOW(DECL_FIELD_OFFSET(FieldDecl));
+      unsigned ByteOffset = TREE_INT_CST_LOW(field_offset);
       BitStart -= ByteOffset * 8;
     }
     
   } else {
-    Constant *Offset = Convert(DECL_FIELD_OFFSET(FieldDecl));
+    Constant *Offset = Convert(field_offset);
     Constant *Ptr = ConstantExpr::getPtrToInt(StructAddrLV, Offset->getType());
     Ptr = ConstantExpr::getAdd(Ptr, Offset);
     FieldPtr = ConstantExpr::getIntToPtr(Ptr, PointerType::get(FieldTy));
_______________________________________________
llvm-commits mailing list
llvm-commits@cs.uiuc.edu
http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits

Reply via email to