Commit 31b752cb authored by Akira Hatanaka's avatar Akira Hatanaka
Browse files

[ObjC][ARC] Check whether the return and parameter types of the old and

new functions are compatible before upgrading a function call to an
intrinsic call.

Sometimes users insert calls to ARC runtime functions that are not
compatible with the corresponding intrinsic functions (for example,
'i8* @objc_storeStrong' instead of 'void @objc_storeStrong'). Don't
upgrade those calls.

rdar://problem/56447127
parent a5376f63
Loading
Loading
Loading
Loading
+22 −1
Original line number Diff line number Diff line
@@ -3877,15 +3877,36 @@ void llvm::UpgradeARCRuntime(Module &M) {
      FunctionType *NewFuncTy = NewFn->getFunctionType();
      SmallVector<Value *, 2> Args;

      // Don't upgrade the intrinsic if it's not valid to bitcast the return
      // value to the return type of the old function.
      if (NewFuncTy->getReturnType() != CI->getType() &&
          !CastInst::castIsValid(Instruction::BitCast, CI,
                                 NewFuncTy->getReturnType()))
        continue;

      bool InvalidCast = false;

      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())
        if (I < NewFuncTy->getNumParams()) {
          // Don't upgrade the intrinsic if it's not valid to bitcast the argument
          // to the parameter type of the new function.
          if (!CastInst::castIsValid(Instruction::BitCast, Arg,
                                     NewFuncTy->getParamType(I))) {
            InvalidCast = true;
            break;
          }
          Arg = Builder.CreateBitCast(Arg, NewFuncTy->getParamType(I));
        }
        Args.push_back(Arg);
      }

      if (InvalidCast)
        continue;

      // Create a call instruction that calls the new function.
      CallInst *NewCall = Builder.CreateCall(NewFuncTy, NewFn, Args);
      NewCall->setTailCallKind(cast<CallInst>(CI)->getTailCallKind());
+1.5 KiB

File added.

No diff preview for this file type.

+21 −0
Original line number Diff line number Diff line
target triple = "arm64-apple-ios7.0"

; RUN: llvm-dis < %S/upgrade-arc-runtime-calls-bitcast.bc | FileCheck %s

; CHECK: tail call i8* @objc_retain(i32 1)
; CHECK: tail call i8* @objc_storeStrong(

define void @testRuntimeCalls(i8* %a, i8** %b) {
  %v6 = tail call i8* @objc_retain(i32 1)
  %1 = tail call i8* @objc_storeStrong(i8** %b, i8* %a)
  ret void
}

declare i8* @objc_retain(i32)
declare i8* @objc_storeStrong(i8**, i8*)

attributes #0 = { nounwind }

!llvm.module.flags = !{!0}

!0 = !{i32 1, !"clang.arc.retainAutoreleasedReturnValueMarker", !"mov\09fp, fp\09\09; marker for objc_retainAutoreleaseReturnValue"}