in the "coerce" case, the ABI handling code ends up making the

alloca for an argument.  Make sure the argument gets the proper
decl alignment, which may be different than the type alignment.

This fixes PR7567

llvm-svn: 107627
This commit is contained in:
Chris Lattner 2010-07-05 20:21:00 +00:00
parent 93b2836267
commit c401de9998
4 changed files with 19 additions and 9 deletions

View File

@ -819,7 +819,7 @@ void CodeGenFunction::EmitFunctionProlog(const CGFunctionInfo &FI,
// initialize the return value. TODO: it might be nice to have // initialize the return value. TODO: it might be nice to have
// a more general mechanism for this that didn't require synthesized // a more general mechanism for this that didn't require synthesized
// return statements. // return statements.
if (const FunctionDecl* FD = dyn_cast_or_null<FunctionDecl>(CurFuncDecl)) { if (const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(CurFuncDecl)) {
if (FD->hasImplicitReturnZero()) { if (FD->hasImplicitReturnZero()) {
QualType RetTy = FD->getResultType().getUnqualifiedType(); QualType RetTy = FD->getResultType().getUnqualifiedType();
const llvm::Type* LLVMTy = CGM.getTypes().ConvertType(RetTy); const llvm::Type* LLVMTy = CGM.getTypes().ConvertType(RetTy);
@ -924,7 +924,9 @@ void CodeGenFunction::EmitFunctionProlog(const CGFunctionInfo &FI,
// FIXME: This is very wasteful; EmitParmDecl is just going to drop the // FIXME: This is very wasteful; EmitParmDecl is just going to drop the
// result in a new alloca anyway, so we could just store into that // result in a new alloca anyway, so we could just store into that
// directly if we broke the abstraction down more. // directly if we broke the abstraction down more.
llvm::Value *V = CreateMemTemp(Ty, "coerce"); llvm::AllocaInst *Alloca = CreateMemTemp(Ty, "coerce");
Alloca->setAlignment(getContext().getDeclAlign(Arg).getQuantity());
llvm::Value *V = Alloca;
// If the coerce-to type is a first class aggregate, we flatten it and // If the coerce-to type is a first class aggregate, we flatten it and
// pass the elements. Either way is semantically identical, but fast-isel // pass the elements. Either way is semantically identical, but fast-isel

View File

@ -44,8 +44,8 @@ void CodeGenFunction::InitTempAlloca(llvm::AllocaInst *Var,
Block->getInstList().insertAfter(&*AllocaInsertPt, Store); Block->getInstList().insertAfter(&*AllocaInsertPt, Store);
} }
llvm::Value *CodeGenFunction::CreateIRTemp(QualType Ty, llvm::AllocaInst *CodeGenFunction::CreateIRTemp(QualType Ty,
const llvm::Twine &Name) { const llvm::Twine &Name) {
llvm::AllocaInst *Alloc = CreateTempAlloca(ConvertType(Ty), Name); llvm::AllocaInst *Alloc = CreateTempAlloca(ConvertType(Ty), Name);
// FIXME: Should we prefer the preferred type alignment here? // FIXME: Should we prefer the preferred type alignment here?
CharUnits Align = getContext().getTypeAlignInChars(Ty); CharUnits Align = getContext().getTypeAlignInChars(Ty);
@ -53,8 +53,8 @@ llvm::Value *CodeGenFunction::CreateIRTemp(QualType Ty,
return Alloc; return Alloc;
} }
llvm::Value *CodeGenFunction::CreateMemTemp(QualType Ty, llvm::AllocaInst *CodeGenFunction::CreateMemTemp(QualType Ty,
const llvm::Twine &Name) { const llvm::Twine &Name) {
llvm::AllocaInst *Alloc = CreateTempAlloca(ConvertTypeForMem(Ty), Name); llvm::AllocaInst *Alloc = CreateTempAlloca(ConvertTypeForMem(Ty), Name);
// FIXME: Should we prefer the preferred type alignment here? // FIXME: Should we prefer the preferred type alignment here?
CharUnits Align = getContext().getTypeAlignInChars(Ty); CharUnits Align = getContext().getTypeAlignInChars(Ty);

View File

@ -698,11 +698,11 @@ public:
/// value needs to be stored into an alloca (for example, to avoid explicit /// value needs to be stored into an alloca (for example, to avoid explicit
/// PHI construction), but the type is the IR type, not the type appropriate /// PHI construction), but the type is the IR type, not the type appropriate
/// for storing in memory. /// for storing in memory.
llvm::Value *CreateIRTemp(QualType T, const llvm::Twine &Name = "tmp"); llvm::AllocaInst *CreateIRTemp(QualType T, const llvm::Twine &Name = "tmp");
/// CreateMemTemp - Create a temporary memory object of the given type, with /// CreateMemTemp - Create a temporary memory object of the given type, with
/// appropriate alignment. /// appropriate alignment.
llvm::Value *CreateMemTemp(QualType T, const llvm::Twine &Name = "tmp"); llvm::AllocaInst *CreateMemTemp(QualType T, const llvm::Twine &Name = "tmp");
/// EvaluateExprAsBool - Perform the usual unary conversions on the specified /// EvaluateExprAsBool - Perform the usual unary conversions on the specified
/// expression and compare the result against zero, returning an Int1Ty value. /// expression and compare the result against zero, returning an Int1Ty value.

View File

@ -71,7 +71,7 @@ void f12_1(struct s12 a0) {}
// Check that sret parameter is accounted for when checking available integer // Check that sret parameter is accounted for when checking available integer
// registers. // registers.
// CHECK: define void @f13(%struct.s13_0* sret %agg.result, i32 %a, i32 %b, i32 %c, i32 %d, %struct.s13_1* byval %e, i32 %f) // CHECK: define void @f13(%struct.s13_0* sret %agg.result, i32 %a, i32 %b, i32 %c, i32 %d, {{.*}}* byval %e, i32 %f)
struct s13_0 { long long f0[3]; }; struct s13_0 { long long f0[3]; };
struct s13_1 { long long f0[2]; }; struct s13_1 { long long f0[2]; };
@ -123,3 +123,11 @@ struct StringRef {
// CHECK: define i8* @f21(i64 %S.coerce0, i8* %S.coerce1) // CHECK: define i8* @f21(i64 %S.coerce0, i8* %S.coerce1)
const char *f21(struct StringRef S) { return S.x+S.Ptr; } const char *f21(struct StringRef S) { return S.x+S.Ptr; }
// PR7567
typedef __attribute__ ((aligned(16))) struct f22s { unsigned long long x[2]; } L;
void f22(L x, L y) { }
// CHECK: @f22
// CHECK: %x = alloca{{.*}}, align 16
// CHECK: %y = alloca{{.*}}, align 16