diff options
author | Evgeniy Stepanov <eugeni.stepanov@gmail.com> | 2012-02-10 09:30:15 +0000 |
---|---|---|
committer | Evgeniy Stepanov <eugeni.stepanov@gmail.com> | 2012-02-10 09:30:15 +0000 |
commit | a6ce20ea10b1788ed1f266d5809a7ac2bca7bf1b (patch) | |
tree | fb0816c15da23e9e93bca948a2a8d6ee41fc94b2 /lib/CodeGen/CGCall.cpp | |
parent | 73d90928c0462daf0665fd7f8e44ca00d896540d (diff) |
Fix function prolog codegen whe coerce-to type is a struct.
This changes function prolog in such a way as to avoid out-of-bounds
stack store in the case when coerce-to type has a larger storage size
than the real argument type.
Fixes PR11905.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@150238 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/CodeGen/CGCall.cpp')
-rw-r--r-- | lib/CodeGen/CGCall.cpp | 39 |
1 files changed, 30 insertions, 9 deletions
diff --git a/lib/CodeGen/CGCall.cpp b/lib/CodeGen/CGCall.cpp index f3e788ba47..b52a8977a7 100644 --- a/lib/CodeGen/CGCall.cpp +++ b/lib/CodeGen/CGCall.cpp @@ -1013,7 +1013,7 @@ void CodeGenFunction::EmitFunctionProlog(const CGFunctionInfo &FI, break; } - llvm::AllocaInst *Alloca = CreateMemTemp(Ty, "coerce"); + llvm::AllocaInst *Alloca = CreateMemTemp(Ty, Arg->getName()); // The alignment we need to use is the max of the requested alignment for // the argument plus the alignment required by our access code below. @@ -1037,15 +1037,36 @@ void CodeGenFunction::EmitFunctionProlog(const CGFunctionInfo &FI, // 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 // and the optimizer generally likes scalar values better than FCAs. - if (llvm::StructType *STy = - dyn_cast<llvm::StructType>(ArgI.getCoerceToType())) { - Ptr = Builder.CreateBitCast(Ptr, llvm::PointerType::getUnqual(STy)); + llvm::StructType *STy = dyn_cast<llvm::StructType>(ArgI.getCoerceToType()); + if (STy && STy->getNumElements() > 1) { + uint64_t SrcSize = CGM.getTargetData().getTypeAllocSize(STy); + llvm::Type *DstTy = + cast<llvm::PointerType>(Ptr->getType())->getElementType(); + uint64_t DstSize = CGM.getTargetData().getTypeAllocSize(DstTy); + + if (SrcSize <= DstSize) { + Ptr = Builder.CreateBitCast(Ptr, llvm::PointerType::getUnqual(STy)); + + for (unsigned i = 0, e = STy->getNumElements(); i != e; ++i) { + assert(AI != Fn->arg_end() && "Argument mismatch!"); + AI->setName(Arg->getName() + ".coerce" + Twine(i)); + llvm::Value *EltPtr = Builder.CreateConstGEP2_32(Ptr, 0, i); + Builder.CreateStore(AI++, EltPtr); + } + } else { + llvm::AllocaInst *TempAlloca = + CreateTempAlloca(ArgI.getCoerceToType(), "coerce"); + TempAlloca->setAlignment(AlignmentToUse); + llvm::Value *TempV = TempAlloca; + + for (unsigned i = 0, e = STy->getNumElements(); i != e; ++i) { + assert(AI != Fn->arg_end() && "Argument mismatch!"); + AI->setName(Arg->getName() + ".coerce" + Twine(i)); + llvm::Value *EltPtr = Builder.CreateConstGEP2_32(TempV, 0, i); + Builder.CreateStore(AI++, EltPtr); + } - for (unsigned i = 0, e = STy->getNumElements(); i != e; ++i) { - assert(AI != Fn->arg_end() && "Argument mismatch!"); - AI->setName(Arg->getName() + ".coerce" + Twine(i)); - llvm::Value *EltPtr = Builder.CreateConstGEP2_32(Ptr, 0, i); - Builder.CreateStore(AI++, EltPtr); + Builder.CreateMemCpy(Ptr, TempV, DstSize, AlignmentToUse); } } else { // Simple case, just do a coerced store of the argument into the alloca. |