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 |