diff options
| author | Akira Hatanaka <ahatanaka@apple.com> | 2019-08-12 23:53:23 +0000 |
|---|---|---|
| committer | Akira Hatanaka <ahatanaka@apple.com> | 2019-08-12 23:53:23 +0000 |
| commit | 6817ce24c17261a8c9ec52d0dfd211ec89483962 (patch) | |
| tree | 2b3cc5cc9b0bb683feb261e47d64e69c5edec95b /llvm/lib/IR | |
| parent | 5b32752d107aec1dbe8676a080c4ae9866a2607c (diff) | |
| download | bcm5719-llvm-6817ce24c17261a8c9ec52d0dfd211ec89483962.tar.gz bcm5719-llvm-6817ce24c17261a8c9ec52d0dfd211ec89483962.zip | |
Do not call replaceAllUsesWith to upgrade calls to ARC runtime functions
to intrinsic calls
This fixes a bug in r368311.
It turns out that the ARC runtime functions in the IR can have pointer
parameter types that are not i8* or i8**. Instead of RAUWing normal
functions with intrinsics, manually bitcast the arguments before passing
them to the intrinsic functions and bitcast the return value back to the
type of the original call instruction.
rdar://problem/54125406
llvm-svn: 368634
Diffstat (limited to 'llvm/lib/IR')
| -rw-r--r-- | llvm/lib/IR/AutoUpgrade.cpp | 40 |
1 files changed, 37 insertions, 3 deletions
diff --git a/llvm/lib/IR/AutoUpgrade.cpp b/llvm/lib/IR/AutoUpgrade.cpp index 6d1305393e1..6e70a0063f0 100644 --- a/llvm/lib/IR/AutoUpgrade.cpp +++ b/llvm/lib/IR/AutoUpgrade.cpp @@ -3855,6 +3855,8 @@ bool llvm::UpgradeRetainReleaseMarker(Module &M) { } void llvm::UpgradeARCRuntimeCalls(Module &M) { + // This lambda converts normal function calls to ARC runtime functions to + // intrinsic calls. auto UpgradeToIntrinsic = [&](const char *OldFunc, llvm::Intrinsic::ID IntrinsicFunc) { Function *Fn = M.getFunction(OldFunc); @@ -3863,11 +3865,43 @@ void llvm::UpgradeARCRuntimeCalls(Module &M) { return; Function *NewFn = llvm::Intrinsic::getDeclaration(&M, IntrinsicFunc); - Fn->replaceAllUsesWith(NewFn); - Fn->eraseFromParent(); + for (Use &U : Fn->uses()) { + CallInst *CI = dyn_cast<CallInst>(U.getUser()); + if (!CI || CI->getCalledFunction() != Fn) + continue; + + IRBuilder<> Builder(CI->getParent(), CI->getIterator()); + FunctionType *NewFuncTy = NewFn->getFunctionType(); + SmallVector<Value *, 2> Args; + + for (unsigned I = 0, E = CI->getNumArgOperands(); I != E; ++I) { + Value *Arg = CI->getArgOperand(I); + // Bitcast argument to the parameter type of the new function if it's + // not a variadic argument. + if (I < NewFuncTy->getNumParams()) + Arg = Builder.CreateBitCast(Arg, NewFuncTy->getParamType(I)); + Args.push_back(Arg); + } + + // Create a call instruction that calls the new function. + CallInst *NewCall = Builder.CreateCall(NewFuncTy, NewFn, Args); + NewCall->setTailCallKind(cast<CallInst>(CI)->getTailCallKind()); + NewCall->setName(CI->getName()); + + // Bitcast the return value back to the type of the old call. + Value *NewRetVal = Builder.CreateBitCast(NewCall, CI->getType()); + + if (!CI->use_empty()) + CI->replaceAllUsesWith(NewRetVal); + CI->eraseFromParent(); + } + + if (Fn->use_empty()) + Fn->eraseFromParent(); }; - // Unconditionally convert "clang.arc.use" to "llvm.objc.clang.arc.use". + // Unconditionally convert a call to "clang.arc.use" to a call to + // "llvm.objc.clang.arc.use". UpgradeToIntrinsic("clang.arc.use", llvm::Intrinsic::objc_clang_arc_use); // Return if the bitcode doesn't have the arm64 retainAutoreleasedReturnValue |

