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 | 3fae4aeae49082b443d9c3f388040c2b719d3f6a (patch) | |
| tree | f40ebeef7d08271254b5688ade630ec6b1d73cbb /clang/lib/CodeGen | |
| parent | f02455e5ee45a96b32dee2f44f9f46e2546beb8e (diff) | |
| download | bcm5719-llvm-3fae4aeae49082b443d9c3f388040c2b719d3f6a.tar.gz bcm5719-llvm-3fae4aeae49082b443d9c3f388040c2b719d3f6a.zip | |
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.
llvm-svn: 150238
Diffstat (limited to 'clang/lib/CodeGen')
| -rw-r--r-- | clang/lib/CodeGen/CGCall.cpp | 39 |
1 files changed, 30 insertions, 9 deletions
diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp index f3e788ba473..b52a8977a7c 100644 --- a/clang/lib/CodeGen/CGCall.cpp +++ b/clang/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. |

