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 |