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