1fe6060f1SDimitry Andric //===- ObjCARCUtil.h - ObjC ARC Utility Functions ---------------*- C++ -*-===// 2fe6060f1SDimitry Andric // 3fe6060f1SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4fe6060f1SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5fe6060f1SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6fe6060f1SDimitry Andric // 7fe6060f1SDimitry Andric //===----------------------------------------------------------------------===// 8fe6060f1SDimitry Andric /// \file 9fe6060f1SDimitry Andric /// This file defines ARC utility functions which are used by various parts of 10fe6060f1SDimitry Andric /// the compiler. 11fe6060f1SDimitry Andric /// 12fe6060f1SDimitry Andric //===----------------------------------------------------------------------===// 13fe6060f1SDimitry Andric 14349cc55cSDimitry Andric #ifndef LLVM_ANALYSIS_OBJCARCUTIL_H 15349cc55cSDimitry Andric #define LLVM_ANALYSIS_OBJCARCUTIL_H 16fe6060f1SDimitry Andric 17349cc55cSDimitry Andric #include "llvm/Analysis/ObjCARCInstKind.h" 18349cc55cSDimitry Andric #include "llvm/IR/Function.h" 19fe6060f1SDimitry Andric #include "llvm/IR/InstrTypes.h" 20fe6060f1SDimitry Andric #include "llvm/IR/LLVMContext.h" 21fe6060f1SDimitry Andric 22fe6060f1SDimitry Andric namespace llvm { 23fe6060f1SDimitry Andric namespace objcarc { 24fe6060f1SDimitry Andric getRVMarkerModuleFlagStr()25fe6060f1SDimitry Andricinline const char *getRVMarkerModuleFlagStr() { 26fe6060f1SDimitry Andric return "clang.arc.retainAutoreleasedReturnValueMarker"; 27fe6060f1SDimitry Andric } 28fe6060f1SDimitry Andric hasAttachedCallOpBundle(const CallBase * CB)29fe6060f1SDimitry Andricinline bool hasAttachedCallOpBundle(const CallBase *CB) { 30fe6060f1SDimitry Andric // Ignore the bundle if the return type is void. Global optimization passes 31fe6060f1SDimitry Andric // can turn the called function's return type to void. That should happen only 32fe6060f1SDimitry Andric // if the call doesn't return and the call to @llvm.objc.clang.arc.noop.use 33fe6060f1SDimitry Andric // no longer consumes the function return or is deleted. In that case, it's 34fe6060f1SDimitry Andric // not necessary to emit the marker instruction or calls to the ARC runtime 35fe6060f1SDimitry Andric // functions. 36fe6060f1SDimitry Andric return !CB->getFunctionType()->getReturnType()->isVoidTy() && 37fe6060f1SDimitry Andric CB->getOperandBundle(LLVMContext::OB_clang_arc_attachedcall) 3881ad6265SDimitry Andric .has_value(); 39fe6060f1SDimitry Andric } 40fe6060f1SDimitry Andric 41349cc55cSDimitry Andric /// This function returns operand bundle clang_arc_attachedcall's argument, 42349cc55cSDimitry Andric /// which is the address of the ARC runtime function. getAttachedARCFunction(const CallBase * CB)43*bdd1243dSDimitry Andricinline std::optional<Function *> getAttachedARCFunction(const CallBase *CB) { 44fe6060f1SDimitry Andric auto B = CB->getOperandBundle(LLVMContext::OB_clang_arc_attachedcall); 451fd87a68SDimitry Andric if (!B) 46*bdd1243dSDimitry Andric return std::nullopt; 47349cc55cSDimitry Andric 48349cc55cSDimitry Andric return cast<Function>(B->Inputs[0]); 49349cc55cSDimitry Andric } 50349cc55cSDimitry Andric 5104eeddc0SDimitry Andric /// Check whether the function is retainRV/unsafeClaimRV. isRetainOrClaimRV(ARCInstKind Kind)52349cc55cSDimitry Andricinline bool isRetainOrClaimRV(ARCInstKind Kind) { 5304eeddc0SDimitry Andric return Kind == ARCInstKind::RetainRV || Kind == ARCInstKind::UnsafeClaimRV; 54349cc55cSDimitry Andric } 55349cc55cSDimitry Andric 56349cc55cSDimitry Andric /// This function returns the ARCInstKind of the function attached to operand 57*bdd1243dSDimitry Andric /// bundle clang_arc_attachedcall. It returns std::nullopt if the call doesn't 58*bdd1243dSDimitry Andric /// have the operand bundle or the operand is null. Otherwise it returns either 59*bdd1243dSDimitry Andric /// RetainRV or UnsafeClaimRV. getAttachedARCFunctionKind(const CallBase * CB)60349cc55cSDimitry Andricinline ARCInstKind getAttachedARCFunctionKind(const CallBase *CB) { 61*bdd1243dSDimitry Andric std::optional<Function *> Fn = getAttachedARCFunction(CB); 6281ad6265SDimitry Andric if (!Fn) 63349cc55cSDimitry Andric return ARCInstKind::None; 64349cc55cSDimitry Andric auto FnClass = GetFunctionClass(*Fn); 65349cc55cSDimitry Andric assert(isRetainOrClaimRV(FnClass) && "unexpected ARC runtime function"); 66349cc55cSDimitry Andric return FnClass; 67fe6060f1SDimitry Andric } 68fe6060f1SDimitry Andric 69fe6060f1SDimitry Andric } // end namespace objcarc 70fe6060f1SDimitry Andric } // end namespace llvm 71fe6060f1SDimitry Andric 72fe6060f1SDimitry Andric #endif 73