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 Andric inline const char *getRVMarkerModuleFlagStr() {
26fe6060f1SDimitry Andric   return "clang.arc.retainAutoreleasedReturnValueMarker";
27fe6060f1SDimitry Andric }
28fe6060f1SDimitry Andric 
hasAttachedCallOpBundle(const CallBase * CB)29fe6060f1SDimitry Andric inline 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 Andric inline 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 Andric inline 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 Andric inline 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