1 //===- ObjCARCUtil.h - ObjC ARC Utility Functions ---------------*- C++ -*-===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 /// \file 9 /// This file defines ARC utility functions which are used by various parts of 10 /// the compiler. 11 /// 12 //===----------------------------------------------------------------------===// 13 14 #ifndef LLVM_ANALYSIS_OBJCARCUTIL_H 15 #define LLVM_ANALYSIS_OBJCARCUTIL_H 16 17 #include "llvm/Analysis/ObjCARCInstKind.h" 18 #include "llvm/IR/Function.h" 19 #include "llvm/IR/InstrTypes.h" 20 #include "llvm/IR/LLVMContext.h" 21 22 namespace llvm { 23 namespace objcarc { 24 getRVMarkerModuleFlagStr()25inline const char *getRVMarkerModuleFlagStr() { 26 return "clang.arc.retainAutoreleasedReturnValueMarker"; 27 } 28 hasAttachedCallOpBundle(const CallBase * CB)29inline bool hasAttachedCallOpBundle(const CallBase *CB) { 30 // Ignore the bundle if the return type is void. Global optimization passes 31 // can turn the called function's return type to void. That should happen only 32 // if the call doesn't return and the call to @llvm.objc.clang.arc.noop.use 33 // no longer consumes the function return or is deleted. In that case, it's 34 // not necessary to emit the marker instruction or calls to the ARC runtime 35 // functions. 36 return !CB->getFunctionType()->getReturnType()->isVoidTy() && 37 CB->getOperandBundle(LLVMContext::OB_clang_arc_attachedcall) 38 .has_value(); 39 } 40 41 /// This function returns operand bundle clang_arc_attachedcall's argument, 42 /// which is the address of the ARC runtime function. getAttachedARCFunction(const CallBase * CB)43inline std::optional<Function *> getAttachedARCFunction(const CallBase *CB) { 44 auto B = CB->getOperandBundle(LLVMContext::OB_clang_arc_attachedcall); 45 if (!B) 46 return std::nullopt; 47 48 return cast<Function>(B->Inputs[0]); 49 } 50 51 /// This function determines whether the clang_arc_attachedcall should be 52 /// emitted with or without the marker. 53 /// Concretely, this is the difference between: 54 /// objc_retainAutoreleasedReturnValue 55 /// and 56 /// objc_claimAutoreleasedReturnValue 57 /// retainRV (and unsafeClaimRV) requires a marker, but claimRV does not. attachedCallOpBundleNeedsMarker(const CallBase * CB)58inline bool attachedCallOpBundleNeedsMarker(const CallBase *CB) { 59 // FIXME: do this on ARCRuntimeEntryPoints, and do the todo above ARCInstKind 60 if (std::optional<Function *> Fn = getAttachedARCFunction(CB)) 61 if ((*Fn)->getName() == "objc_claimAutoreleasedReturnValue") 62 return false; 63 return true; 64 } 65 66 /// Check whether the function is retainRV/unsafeClaimRV. isRetainOrClaimRV(ARCInstKind Kind)67inline bool isRetainOrClaimRV(ARCInstKind Kind) { 68 return Kind == ARCInstKind::RetainRV || Kind == ARCInstKind::UnsafeClaimRV; 69 } 70 71 /// This function returns the ARCInstKind of the function attached to operand 72 /// bundle clang_arc_attachedcall. It returns std::nullopt if the call doesn't 73 /// have the operand bundle or the operand is null. Otherwise it returns either 74 /// RetainRV or UnsafeClaimRV. getAttachedARCFunctionKind(const CallBase * CB)75inline ARCInstKind getAttachedARCFunctionKind(const CallBase *CB) { 76 std::optional<Function *> Fn = getAttachedARCFunction(CB); 77 if (!Fn) 78 return ARCInstKind::None; 79 auto FnClass = GetFunctionClass(*Fn); 80 assert(isRetainOrClaimRV(FnClass) && "unexpected ARC runtime function"); 81 return FnClass; 82 } 83 84 } // end namespace objcarc 85 } // end namespace llvm 86 87 #endif 88