CodeGen: Copy-ctorm must obey the destination's alignment requirement

We would synthesize memcpy intrinsics when emitting calls to trivial C++
constructors but we wouldn't take into account the alignment of the
destination.

llvm-svn: 228061
This commit is contained in:
David Majnemer 2015-02-03 23:04:06 +00:00
parent 2a96704b33
commit fd1e739a44
3 changed files with 29 additions and 3 deletions

View File

@ -1747,9 +1747,10 @@ void CodeGenFunction::EmitCXXConstructorCall(const CXXConstructorDecl *D,
"trivial 1-arg ctor not a copy/move ctor");
const Expr *Arg = E->getArg(0);
QualType Ty = Arg->getType();
QualType SrcTy = Arg->getType();
llvm::Value *Src = EmitLValue(Arg).getAddress();
EmitAggregateCopy(This, Src, Ty);
QualType DestTy = getContext().getTypeDeclType(D->getParent());
EmitAggregateCopyCtor(This, Src, DestTy, SrcTy);
return;
}
@ -1789,7 +1790,9 @@ CodeGenFunction::EmitSynthesizedCXXCopyCtorCall(const CXXConstructorDecl *D,
assert(E->getNumArgs() == 1 && "unexpected argcount for trivial ctor");
assert(D->isCopyOrMoveConstructor() &&
"trivial 1-arg ctor not a copy/move ctor");
EmitAggregateCopy(This, Src, E->arg_begin()->getType());
EmitAggregateCopyCtor(This, Src,
getContext().getTypeDeclType(D->getParent()),
E->arg_begin()->getType());
return;
}
llvm::Value *Callee = CGM.getAddrOfCXXStructor(D, StructorType::Complete);

View File

@ -1559,6 +1559,15 @@ public:
true);
}
void EmitAggregateCopyCtor(llvm::Value *DestPtr, llvm::Value *SrcPtr,
QualType DestTy, QualType SrcTy) {
CharUnits DestTypeAlign = getContext().getTypeAlignInChars(DestTy);
CharUnits SrcTypeAlign = getContext().getTypeAlignInChars(SrcTy);
EmitAggregateCopy(DestPtr, SrcPtr, SrcTy, /*IsVolatile=*/false,
std::min(DestTypeAlign, SrcTypeAlign),
/*IsAssignment=*/false);
}
/// EmitAggregateCopy - Emit an aggregate copy.
///
/// \param isVolatile - True iff either the source or the destination is

View File

@ -43,3 +43,17 @@ int main() {
S s;
Call(s);
}
struct V {
int x;
};
typedef V V_over_aligned __attribute((aligned(8)));
extern const V_over_aligned gv1 = {};
extern "C" V f() { return gv1; }
// Make sure that we obey the destination's alignment requirements when emitting
// the copy.
// CHECK-LABEL: define i32 @f()
// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64({{.*}}, i8* bitcast (%struct.V* @gv1 to i8*), i64 4, i32 4, i1 false)