From 891835ae0f801da0d25503c0a66a218bf4629c59 Mon Sep 17 00:00:00 2001 From: Reid Kleckner Date: Wed, 26 Mar 2014 22:26:35 +0000 Subject: [PATCH] CloneFunction: Clone all attributes, including the CC Summary: Tested with a unit test because we don't appear to have any transforms that use this other than ASan, I think. Fixes PR17935. Reviewers: nicholas CC: llvm-commits Differential Revision: http://llvm-reviews.chandlerc.com/D3194 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@204866 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Transforms/Utils/CloneFunction.cpp | 30 ++++++++++++++------------ unittests/Transforms/Utils/Cloning.cpp | 23 ++++++++++++++++++++ 2 files changed, 39 insertions(+), 14 deletions(-) diff --git a/lib/Transforms/Utils/CloneFunction.cpp b/lib/Transforms/Utils/CloneFunction.cpp index 8df3ca0f15a..a199086aedb 100644 --- a/lib/Transforms/Utils/CloneFunction.cpp +++ b/lib/Transforms/Utils/CloneFunction.cpp @@ -89,26 +89,28 @@ void llvm::CloneFunctionInto(Function *NewFunc, const Function *OldFunc, assert(VMap.count(I) && "No mapping from source argument specified!"); #endif + // Copy all attributes other than those stored in the AttributeSet. We need + // to remap the parameter indices of the AttributeSet. + AttributeSet NewAttrs = NewFunc->getAttributes(); + NewFunc->copyAttributesFrom(OldFunc); + NewFunc->setAttributes(NewAttrs); + AttributeSet OldAttrs = OldFunc->getAttributes(); // Clone any argument attributes that are present in the VMap. - for (Function::const_arg_iterator I = OldFunc->arg_begin(), - E = OldFunc->arg_end(); - I != E; ++I) - if (Argument *Anew = dyn_cast(VMap[I])) { + for (const Argument &OldArg : OldFunc->args()) + if (Argument *NewArg = dyn_cast(VMap[&OldArg])) { AttributeSet attrs = - OldAttrs.getParamAttributes(I->getArgNo() + 1); + OldAttrs.getParamAttributes(OldArg.getArgNo() + 1); if (attrs.getNumSlots() > 0) - Anew->addAttr(attrs); + NewArg->addAttr(attrs); } - NewFunc->setAttributes(NewFunc->getAttributes() - .addAttributes(NewFunc->getContext(), - AttributeSet::ReturnIndex, - OldAttrs.getRetAttributes())); - NewFunc->setAttributes(NewFunc->getAttributes() - .addAttributes(NewFunc->getContext(), - AttributeSet::FunctionIndex, - OldAttrs.getFnAttributes())); + NewFunc->setAttributes( + NewFunc->getAttributes() + .addAttributes(NewFunc->getContext(), AttributeSet::ReturnIndex, + OldAttrs.getRetAttributes()) + .addAttributes(NewFunc->getContext(), AttributeSet::FunctionIndex, + OldAttrs.getFnAttributes())); // Loop over all of the basic blocks in the function, cloning them as // appropriate. Note that we save BE this way in order to handle cloning of diff --git a/unittests/Transforms/Utils/Cloning.cpp b/unittests/Transforms/Utils/Cloning.cpp index 6dec807b0c7..fb27dc17353 100644 --- a/unittests/Transforms/Utils/Cloning.cpp +++ b/unittests/Transforms/Utils/Cloning.cpp @@ -180,6 +180,29 @@ TEST_F(CloneInstruction, Attributes) { delete F2; } +TEST_F(CloneInstruction, CallingConvention) { + Type *ArgTy1[] = { Type::getInt32PtrTy(context) }; + FunctionType *FT1 = FunctionType::get(Type::getVoidTy(context), ArgTy1, false); + + Function *F1 = Function::Create(FT1, Function::ExternalLinkage); + F1->setCallingConv(CallingConv::Cold); + BasicBlock *BB = BasicBlock::Create(context, "", F1); + IRBuilder<> Builder(BB); + Builder.CreateRetVoid(); + + Function *F2 = Function::Create(FT1, Function::ExternalLinkage); + + SmallVector Returns; + ValueToValueMapTy VMap; + VMap[F1->arg_begin()] = F2->arg_begin(); + + CloneFunctionInto(F2, F1, VMap, false, Returns); + EXPECT_EQ(CallingConv::Cold, F2->getCallingConv()); + + delete F1; + delete F2; +} + class CloneFunc : public ::testing::Test { protected: virtual void SetUp() {