diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp index 562c17ded393..e8d99e2f5a01 100644 --- a/clang/lib/CodeGen/CGCall.cpp +++ b/clang/lib/CodeGen/CGCall.cpp @@ -2073,8 +2073,25 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo, // and the optimizer generally likes scalar values better than FCAs. if (llvm::StructType *STy = dyn_cast(ArgInfo.getCoerceToType())) { - SrcPtr = Builder.CreateBitCast(SrcPtr, - llvm::PointerType::getUnqual(STy)); + llvm::Type *SrcTy = + cast(SrcPtr->getType())->getElementType(); + uint64_t SrcSize = CGM.getDataLayout().getTypeAllocSize(SrcTy); + uint64_t DstSize = CGM.getDataLayout().getTypeAllocSize(STy); + + // If the source type is smaller than the destination type of the + // coerce-to logic, copy the source value into a temp alloca the size + // of the destination type to allow loading all of it. The bits past + // the source value are left undef. + if (SrcSize < DstSize) { + llvm::AllocaInst *TempAlloca + = CreateTempAlloca(STy, SrcPtr->getName() + ".coerce"); + Builder.CreateMemCpy(TempAlloca, SrcPtr, SrcSize, 0); + SrcPtr = TempAlloca; + } else { + SrcPtr = Builder.CreateBitCast(SrcPtr, + llvm::PointerType::getUnqual(STy)); + } + for (unsigned i = 0, e = STy->getNumElements(); i != e; ++i) { llvm::Value *EltPtr = Builder.CreateConstGEP2_32(SrcPtr, 0, i); llvm::LoadInst *LI = Builder.CreateLoad(EltPtr); diff --git a/clang/test/CodeGen/arm-arguments.c b/clang/test/CodeGen/arm-arguments.c index 2ec729eb9b3d..8aa33f696d72 100644 --- a/clang/test/CodeGen/arm-arguments.c +++ b/clang/test/CodeGen/arm-arguments.c @@ -178,3 +178,16 @@ struct s33 { char buf[32*32]; }; void f33(struct s33 s) { } // APCS-GNU: define void @f33(%struct.s33* byval %s) // AAPCS: define arm_aapcscc void @f33(%struct.s33* byval %s) + +// PR14048 +struct s34 { char c; }; +void f34(struct s34 s); +void g34(struct s34 *s) { f34(*s); } +// APCS-GNU: @g34(%struct.s34* %s) +// APCS-GNU: %[[a:.*]] = alloca { [1 x i32] } +// APCS-GNU: %[[gep:.*]] = getelementptr { [1 x i32] }* %[[a]], i32 0, i32 0 +// APCS-GNU: load [1 x i32]* %[[gep]] +// AAPCS: @g34(%struct.s34* %s) +// AAPCS: %[[a:.*]] = alloca { [1 x i32] } +// AAPCS: %[[gep:.*]] = getelementptr { [1 x i32] }* %[[a]], i32 0, i32 0 +// AAPCS: load [1 x i32]* %[[gep]]