Hi!
when reading the comments in CodeGenFunction::EmitAggregateCopy
there seem to be two problems:
1. "Aggregate assignment turns into llvm.memcpy. This is almost valid per
C99 6.5.16.1p3"
For me, "almost valid" means that it is valid for 99% of the cases but there should
be the possibility to switch it off
2. "FIXME: If we have a volatile struct, the optimizer can remove what might
appear to be `extra' memory ops"
This sounds like the current implementation can produce incorrect code for
volatile struct variables.
This is my alternative implementation based on element wise copy of all fields.
I would suggest that it is used if isVolatile is true or if a flag in TargetInfo
indicates that it always should be used. This way the 99% of the cases
continue using memcpy.
const clang::RecordType* recordType = Ty->getAs<clang::RecordType>();
// get record decl
clang::RecordDecl* recordDecl = recordType->getDecl();
// iterate over fields
clang::CodeGen::CodeGenTypes& codeGenTypes = CGM.getTypes();
const clang::CodeGen::CGRecordLayout& layout = codeGenTypes.getCGRecordLayout(recordDecl);
clang::RecordDecl::field_iterator it = recordDecl->field_begin();
clang::RecordDecl::field_iterator end = recordDecl->field_end();
for (; it != end; ++it)
{
clang::FieldDecl* fieldDecl = *it;
int fieldIndex = layout.getLLVMFieldNo(fieldDecl);
llvm::Value *SrcFieldPtr = Builder.CreateConstInBoundsGEP2_32(SrcPtr, 0, fieldIndex);
llvm::Value *DestFieldPtr = Builder.CreateConstInBoundsGEP2_32(DestPtr, 0, fieldIndex);
// check if field is an aggregate
QualType fieldType = fieldDecl->getType();
if (fieldType->getAs<clang::RecordType>() != NULL)
{
// copy nested aggregate
EmitAggregateCopy(DestFieldPtr, SrcFieldPtr, fieldType, isVolatile);
}
else
{
// copy value
llvm::Value *Element = Builder.CreateLoad(SrcFieldPtr, isVolatile, "tmp");
Builder.CreateStore(Element, DestFieldPtr, isVolatile);
}
}
-Jochen