Details | Last modification | View Log | RSS feed
| Rev | Author | Line No. | Line | 
|---|---|---|---|
| 14 | pmbaty | 1 | //===- AbstractCallSite.h - Abstract call sites -----------------*- 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 | // | ||
| 9 | // This file defines the AbstractCallSite class, which is a is a wrapper that | ||
| 10 | // allows treating direct, indirect, and callback calls the same. | ||
| 11 | // | ||
| 12 | //===----------------------------------------------------------------------===// | ||
| 13 | |||
| 14 | #ifndef LLVM_IR_ABSTRACTCALLSITE_H | ||
| 15 | #define LLVM_IR_ABSTRACTCALLSITE_H | ||
| 16 | |||
| 17 | #include "llvm/IR/Constants.h" | ||
| 18 | #include "llvm/IR/Function.h" | ||
| 19 | #include "llvm/IR/InstrTypes.h" | ||
| 20 | #include "llvm/IR/Value.h" | ||
| 21 | #include <cassert> | ||
| 22 | |||
| 23 | namespace llvm { | ||
| 24 | |||
| 25 | class Argument; | ||
| 26 | class Use; | ||
| 27 | |||
| 28 | /// AbstractCallSite | ||
| 29 | /// | ||
| 30 | /// An abstract call site is a wrapper that allows to treat direct, | ||
| 31 | /// indirect, and callback calls the same. If an abstract call site | ||
| 32 | /// represents a direct or indirect call site it behaves like a stripped | ||
| 33 | /// down version of a normal call site object. The abstract call site can | ||
| 34 | /// also represent a callback call, thus the fact that the initially | ||
| 35 | /// called function (=broker) may invoke a third one (=callback callee). | ||
| 36 | /// In this case, the abstract call site hides the middle man, hence the | ||
| 37 | /// broker function. The result is a representation of the callback call, | ||
| 38 | /// inside the broker, but in the context of the original call to the broker. | ||
| 39 | /// | ||
| 40 | /// There are up to three functions involved when we talk about callback call | ||
| 41 | /// sites. The caller (1), which invokes the broker function. The broker | ||
| 42 | /// function (2), that will invoke the callee zero or more times. And finally | ||
| 43 | /// the callee (3), which is the target of the callback call. | ||
| 44 | /// | ||
| 45 | /// The abstract call site will handle the mapping from parameters to arguments | ||
| 46 | /// depending on the semantic of the broker function. However, it is important | ||
| 47 | /// to note that the mapping is often partial. Thus, some arguments of the | ||
| 48 | /// call/invoke instruction are mapped to parameters of the callee while others | ||
| 49 | /// are not. | ||
| 50 | class AbstractCallSite { | ||
| 51 | public: | ||
| 52 | |||
| 53 |   /// The encoding of a callback with regards to the underlying instruction. | ||
| 54 | struct CallbackInfo { | ||
| 55 | |||
| 56 |     /// For direct/indirect calls the parameter encoding is empty. If it is not, | ||
| 57 |     /// the abstract call site represents a callback. In that case, the first | ||
| 58 |     /// element of the encoding vector represents which argument of the call | ||
| 59 |     /// site CB is the callback callee. The remaining elements map parameters | ||
| 60 |     /// (identified by their position) to the arguments that will be passed | ||
| 61 |     /// through (also identified by position but in the call site instruction). | ||
| 62 |     /// | ||
| 63 |     /// NOTE that we use LLVM argument numbers (starting at 0) and not | ||
| 64 |     /// clang/source argument numbers (starting at 1). The -1 entries represent | ||
| 65 |     /// unknown values that are passed to the callee. | ||
| 66 | using ParameterEncodingTy = SmallVector<int, 0>; | ||
| 67 |     ParameterEncodingTy ParameterEncoding; | ||
| 68 | |||
| 69 | }; | ||
| 70 | |||
| 71 | private: | ||
| 72 | |||
| 73 |   /// The underlying call site: | ||
| 74 |   ///   caller -> callee,             if this is a direct or indirect call site | ||
| 75 |   ///   caller -> broker function,    if this is a callback call site | ||
| 76 | CallBase *CB; | ||
| 77 | |||
| 78 |   /// The encoding of a callback with regards to the underlying instruction. | ||
| 79 |   CallbackInfo CI; | ||
| 80 | |||
| 81 | public: | ||
| 82 |   /// Sole constructor for abstract call sites (ACS). | ||
| 83 |   /// | ||
| 84 |   /// An abstract call site can only be constructed through a llvm::Use because | ||
| 85 |   /// each operand (=use) of an instruction could potentially be a different | ||
| 86 |   /// abstract call site. Furthermore, even if the value of the llvm::Use is the | ||
| 87 |   /// same, and the user is as well, the abstract call sites might not be. | ||
| 88 |   /// | ||
| 89 |   /// If a use is not associated with an abstract call site the constructed ACS | ||
| 90 |   /// will evaluate to false if converted to a boolean. | ||
| 91 |   /// | ||
| 92 |   /// If the use is the callee use of a call or invoke instruction, the | ||
| 93 |   /// constructed abstract call site will behave as a llvm::CallSite would. | ||
| 94 |   /// | ||
| 95 |   /// If the use is not a callee use of a call or invoke instruction, the | ||
| 96 |   /// callback metadata is used to determine the argument <-> parameter mapping | ||
| 97 |   /// as well as the callee of the abstract call site. | ||
| 98 | AbstractCallSite(const Use *U); | ||
| 99 | |||
| 100 |   /// Add operand uses of \p CB that represent callback uses into | ||
| 101 |   /// \p CallbackUses. | ||
| 102 |   /// | ||
| 103 |   /// All uses added to \p CallbackUses can be used to create abstract call | ||
| 104 |   /// sites for which AbstractCallSite::isCallbackCall() will return true. | ||
| 105 | static void getCallbackUses(const CallBase &CB, | ||
| 106 | SmallVectorImpl<const Use *> &CallbackUses); | ||
| 107 | |||
| 108 |   /// Conversion operator to conveniently check for a valid/initialized ACS. | ||
| 109 | explicit operator bool() const { return CB != nullptr; } | ||
| 110 | |||
| 111 |   /// Return the underlying instruction. | ||
| 112 | CallBase *getInstruction() const { return CB; } | ||
| 113 | |||
| 114 |   /// Return true if this ACS represents a direct call. | ||
| 115 | bool isDirectCall() const { | ||
| 116 | return !isCallbackCall() && !CB->isIndirectCall(); | ||
| 117 |   } | ||
| 118 | |||
| 119 |   /// Return true if this ACS represents an indirect call. | ||
| 120 | bool isIndirectCall() const { | ||
| 121 | return !isCallbackCall() && CB->isIndirectCall(); | ||
| 122 |   } | ||
| 123 | |||
| 124 |   /// Return true if this ACS represents a callback call. | ||
| 125 | bool isCallbackCall() const { | ||
| 126 |     // For a callback call site the callee is ALWAYS stored first in the | ||
| 127 |     // transitive values vector. Thus, a non-empty vector indicates a callback. | ||
| 128 | return !CI.ParameterEncoding.empty(); | ||
| 129 |   } | ||
| 130 | |||
| 131 |   /// Return true if @p UI is the use that defines the callee of this ACS. | ||
| 132 | bool isCallee(Value::const_user_iterator UI) const { | ||
| 133 | return isCallee(&UI.getUse()); | ||
| 134 |   } | ||
| 135 | |||
| 136 |   /// Return true if @p U is the use that defines the callee of this ACS. | ||
| 137 | bool isCallee(const Use *U) const { | ||
| 138 | if (isDirectCall()) | ||
| 139 | return CB->isCallee(U); | ||
| 140 | |||
| 141 | assert(!CI.ParameterEncoding.empty() && | ||
| 142 | "Callback without parameter encoding!"); | ||
| 143 | |||
| 144 |     // If the use is actually in a constant cast expression which itself | ||
| 145 |     // has only one use, we look through the constant cast expression. | ||
| 146 | if (auto *CE = dyn_cast<ConstantExpr>(U->getUser())) | ||
| 147 | if (CE->hasOneUse() && CE->isCast()) | ||
| 148 | U = &*CE->use_begin(); | ||
| 149 | |||
| 150 | return (int)CB->getArgOperandNo(U) == CI.ParameterEncoding[0]; | ||
| 151 |   } | ||
| 152 | |||
| 153 |   /// Return the number of parameters of the callee. | ||
| 154 | unsigned getNumArgOperands() const { | ||
| 155 | if (isDirectCall()) | ||
| 156 | return CB->arg_size(); | ||
| 157 |     // Subtract 1 for the callee encoding. | ||
| 158 | return CI.ParameterEncoding.size() - 1; | ||
| 159 |   } | ||
| 160 | |||
| 161 |   /// Return the operand index of the underlying instruction associated with @p | ||
| 162 |   /// Arg. | ||
| 163 | int getCallArgOperandNo(Argument &Arg) const { | ||
| 164 | return getCallArgOperandNo(Arg.getArgNo()); | ||
| 165 |   } | ||
| 166 | |||
| 167 |   /// Return the operand index of the underlying instruction associated with | ||
| 168 |   /// the function parameter number @p ArgNo or -1 if there is none. | ||
| 169 | int getCallArgOperandNo(unsigned ArgNo) const { | ||
| 170 | if (isDirectCall()) | ||
| 171 | return ArgNo; | ||
| 172 |     // Add 1 for the callee encoding. | ||
| 173 | return CI.ParameterEncoding[ArgNo + 1]; | ||
| 174 |   } | ||
| 175 | |||
| 176 |   /// Return the operand of the underlying instruction associated with @p Arg. | ||
| 177 | Value *getCallArgOperand(Argument &Arg) const { | ||
| 178 | return getCallArgOperand(Arg.getArgNo()); | ||
| 179 |   } | ||
| 180 | |||
| 181 |   /// Return the operand of the underlying instruction associated with the | ||
| 182 |   /// function parameter number @p ArgNo or nullptr if there is none. | ||
| 183 | Value *getCallArgOperand(unsigned ArgNo) const { | ||
| 184 | if (isDirectCall()) | ||
| 185 | return CB->getArgOperand(ArgNo); | ||
| 186 |     // Add 1 for the callee encoding. | ||
| 187 | return CI.ParameterEncoding[ArgNo + 1] >= 0 | ||
| 188 | ? CB->getArgOperand(CI.ParameterEncoding[ArgNo + 1]) | ||
| 189 | : nullptr; | ||
| 190 |   } | ||
| 191 | |||
| 192 |   /// Return the operand index of the underlying instruction associated with the | ||
| 193 |   /// callee of this ACS. Only valid for callback calls! | ||
| 194 | int getCallArgOperandNoForCallee() const { | ||
| 195 | assert(isCallbackCall()); | ||
| 196 | assert(CI.ParameterEncoding.size() && CI.ParameterEncoding[0] >= 0); | ||
| 197 | return CI.ParameterEncoding[0]; | ||
| 198 |   } | ||
| 199 | |||
| 200 |   /// Return the use of the callee value in the underlying instruction. Only | ||
| 201 |   /// valid for callback calls! | ||
| 202 | const Use &getCalleeUseForCallback() const { | ||
| 203 | int CalleeArgIdx = getCallArgOperandNoForCallee(); | ||
| 204 | assert(CalleeArgIdx >= 0 && | ||
| 205 | unsigned(CalleeArgIdx) < getInstruction()->getNumOperands()); | ||
| 206 | return getInstruction()->getOperandUse(CalleeArgIdx); | ||
| 207 |   } | ||
| 208 | |||
| 209 |   /// Return the pointer to function that is being called. | ||
| 210 | Value *getCalledOperand() const { | ||
| 211 | if (isDirectCall()) | ||
| 212 | return CB->getCalledOperand(); | ||
| 213 | return CB->getArgOperand(getCallArgOperandNoForCallee()); | ||
| 214 |   } | ||
| 215 | |||
| 216 |   /// Return the function being called if this is a direct call, otherwise | ||
| 217 |   /// return null (if it's an indirect call). | ||
| 218 | Function *getCalledFunction() const { | ||
| 219 | Value *V = getCalledOperand(); | ||
| 220 | return V ? dyn_cast<Function>(V->stripPointerCasts()) : nullptr; | ||
| 221 |   } | ||
| 222 | }; | ||
| 223 | |||
| 224 | /// Apply function Func to each CB's callback call site. | ||
| 225 | template <typename UnaryFunction> | ||
| 226 | void forEachCallbackCallSite(const CallBase &CB, UnaryFunction Func) { | ||
| 227 | SmallVector<const Use *, 4u> CallbackUses; | ||
| 228 | AbstractCallSite::getCallbackUses(CB, CallbackUses); | ||
| 229 | for (const Use *U : CallbackUses) { | ||
| 230 | AbstractCallSite ACS(U); | ||
| 231 | assert(ACS && ACS.isCallbackCall() && "must be a callback call"); | ||
| 232 | Func(ACS); | ||
| 233 |   } | ||
| 234 | } | ||
| 235 | |||
| 236 | /// Apply function Func to each CB's callback function. | ||
| 237 | template <typename UnaryFunction> | ||
| 238 | void forEachCallbackFunction(const CallBase &CB, UnaryFunction Func) { | ||
| 239 | forEachCallbackCallSite(CB, [&Func](AbstractCallSite &ACS) { | ||
| 240 | if (Function *Callback = ACS.getCalledFunction()) | ||
| 241 | Func(Callback); | ||
| 242 | }); | ||
| 243 | } | ||
| 244 | |||
| 245 | } // end namespace llvm | ||
| 246 | |||
| 247 | #endif // LLVM_IR_ABSTRACTCALLSITE_H |