Line data Source code
1 : //===- llvm/IR/Statepoint.h - gc.statepoint utilities -----------*- C++ -*-===//
2 : //
3 : // The LLVM Compiler Infrastructure
4 : //
5 : // This file is distributed under the University of Illinois Open Source
6 : // License. See LICENSE.TXT for details.
7 : //
8 : //===----------------------------------------------------------------------===//
9 : //
10 : // This file contains utility functions and a wrapper class analogous to
11 : // CallSite for accessing the fields of gc.statepoint, gc.relocate,
12 : // gc.result intrinsics; and some general utilities helpful when dealing with
13 : // gc.statepoint.
14 : //
15 : //===----------------------------------------------------------------------===//
16 :
17 : #ifndef LLVM_IR_STATEPOINT_H
18 : #define LLVM_IR_STATEPOINT_H
19 :
20 : #include "llvm/ADT/Optional.h"
21 : #include "llvm/ADT/iterator_range.h"
22 : #include "llvm/IR/Attributes.h"
23 : #include "llvm/IR/BasicBlock.h"
24 : #include "llvm/IR/CallSite.h"
25 : #include "llvm/IR/Constants.h"
26 : #include "llvm/IR/Function.h"
27 : #include "llvm/IR/Instruction.h"
28 : #include "llvm/IR/Instructions.h"
29 : #include "llvm/IR/IntrinsicInst.h"
30 : #include "llvm/IR/Intrinsics.h"
31 : #include "llvm/Support/Casting.h"
32 : #include "llvm/Support/MathExtras.h"
33 : #include <cassert>
34 : #include <cstddef>
35 : #include <cstdint>
36 : #include <vector>
37 :
38 : namespace llvm {
39 :
40 : /// The statepoint intrinsic accepts a set of flags as its third argument.
41 : /// Valid values come out of this set.
42 : enum class StatepointFlags {
43 : None = 0,
44 : GCTransition = 1, ///< Indicates that this statepoint is a transition from
45 : ///< GC-aware code to code that is not GC-aware.
46 : /// Mark the deopt arguments associated with the statepoint as only being
47 : /// "live-in". By default, deopt arguments are "live-through". "live-through"
48 : /// requires that they the value be live on entry, on exit, and at any point
49 : /// during the call. "live-in" only requires the value be available at the
50 : /// start of the call. In particular, "live-in" values can be placed in
51 : /// unused argument registers or other non-callee saved registers.
52 : DeoptLiveIn = 2,
53 :
54 : MaskAll = 3 ///< A bitmask that includes all valid flags.
55 : };
56 :
57 : class GCRelocateInst;
58 : class GCResultInst;
59 :
60 : bool isStatepoint(ImmutableCallSite CS);
61 : bool isStatepoint(const Value *V);
62 : bool isStatepoint(const Value &V);
63 :
64 : bool isGCRelocate(ImmutableCallSite CS);
65 : bool isGCRelocate(const Value *V);
66 :
67 : bool isGCResult(ImmutableCallSite CS);
68 : bool isGCResult(const Value *V);
69 :
70 : /// Analogous to CallSiteBase, this provides most of the actual
71 : /// functionality for Statepoint and ImmutableStatepoint. It is
72 : /// templatized to allow easily specializing of const and non-const
73 : /// concrete subtypes. This is structured analogous to CallSite
74 : /// rather than the IntrinsicInst.h helpers since we need to support
75 : /// invokable statepoints.
76 : template <typename FunTy, typename InstructionTy, typename ValueTy,
77 : typename CallSiteTy>
78 : class StatepointBase {
79 : CallSiteTy StatepointCS;
80 :
81 : protected:
82 727 : explicit StatepointBase(InstructionTy *I) {
83 727 : if (isStatepoint(I)) {
84 727 : StatepointCS = CallSiteTy(I);
85 : assert(StatepointCS && "isStatepoint implies CallSite");
86 : }
87 727 : }
88 :
89 : explicit StatepointBase(CallSiteTy CS) {
90 : if (isStatepoint(CS))
91 : StatepointCS = CS;
92 : }
93 :
94 : public:
95 : using arg_iterator = typename CallSiteTy::arg_iterator;
96 :
97 : enum {
98 : IDPos = 0,
99 : NumPatchBytesPos = 1,
100 : CalledFunctionPos = 2,
101 : NumCallArgsPos = 3,
102 : FlagsPos = 4,
103 : CallArgsBeginPos = 5,
104 : };
105 :
106 : void *operator new(size_t, unsigned) = delete;
107 : void *operator new(size_t s) = delete;
108 :
109 : explicit operator bool() const {
110 : // We do not assign non-statepoint CallSites to StatepointCS.
111 : return (bool)StatepointCS;
112 : }
113 :
114 : /// Return the underlying CallSite.
115 0 : CallSiteTy getCallSite() const {
116 : assert(*this && "check validity first!");
117 0 : return StatepointCS;
118 : }
119 :
120 67 : uint64_t getFlags() const {
121 : return cast<ConstantInt>(getCallSite().getArgument(FlagsPos))
122 67 : ->getZExtValue();
123 : }
124 :
125 : /// Return the ID associated with this statepoint.
126 67 : uint64_t getID() const {
127 : const Value *IDVal = getCallSite().getArgument(IDPos);
128 67 : return cast<ConstantInt>(IDVal)->getZExtValue();
129 : }
130 :
131 : /// Return the number of patchable bytes associated with this statepoint.
132 134 : uint32_t getNumPatchBytes() const {
133 : const Value *NumPatchBytesVal = getCallSite().getArgument(NumPatchBytesPos);
134 : uint64_t NumPatchBytes =
135 : cast<ConstantInt>(NumPatchBytesVal)->getZExtValue();
136 : assert(isInt<32>(NumPatchBytes) && "should fit in 32 bits!");
137 134 : return NumPatchBytes;
138 : }
139 :
140 : /// Return the value actually being called or invoked.
141 : ValueTy *getCalledValue() const {
142 : return getCallSite().getArgument(CalledFunctionPos);
143 : }
144 :
145 : InstructionTy *getInstruction() const {
146 : return getCallSite().getInstruction();
147 : }
148 :
149 : /// Return the function being called if this is a direct call, otherwise
150 : /// return null (if it's an indirect call).
151 : FunTy *getCalledFunction() const {
152 : return dyn_cast<Function>(getCalledValue());
153 : }
154 :
155 : /// Return the caller function for this statepoint.
156 : FunTy *getCaller() const { return getCallSite().getCaller(); }
157 :
158 : /// Determine if the statepoint cannot unwind.
159 : bool doesNotThrow() const {
160 : Function *F = getCalledFunction();
161 : return getCallSite().doesNotThrow() || (F ? F->doesNotThrow() : false);
162 : }
163 :
164 : /// Return the type of the value returned by the call underlying the
165 : /// statepoint.
166 134 : Type *getActualReturnType() const {
167 134 : auto *FTy = cast<FunctionType>(
168 : cast<PointerType>(getCalledValue()->getType())->getElementType());
169 268 : return FTy->getReturnType();
170 : }
171 :
172 : /// Number of arguments to be passed to the actual callee.
173 993 : int getNumCallArgs() const {
174 : const Value *NumCallArgsVal = getCallSite().getArgument(NumCallArgsPos);
175 993 : return cast<ConstantInt>(NumCallArgsVal)->getZExtValue();
176 : }
177 :
178 926 : size_t arg_size() const { return getNumCallArgs(); }
179 : typename CallSiteTy::arg_iterator arg_begin() const {
180 : assert(CallArgsBeginPos <= (int)getCallSite().arg_size());
181 : return getCallSite().arg_begin() + CallArgsBeginPos;
182 : }
183 926 : typename CallSiteTy::arg_iterator arg_end() const {
184 926 : auto I = arg_begin() + arg_size();
185 : assert((getCallSite().arg_end() - I) >= 0);
186 926 : return I;
187 : }
188 :
189 : ValueTy *getArgument(unsigned Index) {
190 : assert(Index < arg_size() && "out of bounds!");
191 : return *(arg_begin() + Index);
192 : }
193 :
194 : /// range adapter for call arguments
195 : iterator_range<arg_iterator> call_args() const {
196 : return make_range(arg_begin(), arg_end());
197 : }
198 :
199 : /// Return true if the call or the callee has the given attribute.
200 : bool paramHasAttr(unsigned i, Attribute::AttrKind A) const {
201 : Function *F = getCalledFunction();
202 : return getCallSite().paramHasAttr(i + CallArgsBeginPos, A) ||
203 : (F ? F->getAttributes().hasAttribute(i, A) : false);
204 : }
205 :
206 : /// Number of GC transition args.
207 : int getNumTotalGCTransitionArgs() const {
208 926 : const Value *NumGCTransitionArgs = *arg_end();
209 926 : return cast<ConstantInt>(NumGCTransitionArgs)->getZExtValue();
210 : }
211 : typename CallSiteTy::arg_iterator gc_transition_args_begin() const {
212 926 : auto I = arg_end() + 1;
213 : assert((getCallSite().arg_end() - I) >= 0);
214 : return I;
215 : }
216 926 : typename CallSiteTy::arg_iterator gc_transition_args_end() const {
217 926 : auto I = gc_transition_args_begin() + getNumTotalGCTransitionArgs();
218 : assert((getCallSite().arg_end() - I) >= 0);
219 926 : return I;
220 : }
221 :
222 : /// range adapter for GC transition arguments
223 : iterator_range<arg_iterator> gc_transition_args() const {
224 : return make_range(gc_transition_args_begin(), gc_transition_args_end());
225 : }
226 :
227 : /// Number of additional arguments excluding those intended
228 : /// for garbage collection.
229 : int getNumTotalVMSArgs() const {
230 859 : const Value *NumVMSArgs = *gc_transition_args_end();
231 859 : return cast<ConstantInt>(NumVMSArgs)->getZExtValue();
232 : }
233 :
234 : typename CallSiteTy::arg_iterator deopt_begin() const {
235 725 : auto I = gc_transition_args_end() + 1;
236 : assert((getCallSite().arg_end() - I) >= 0);
237 : return I;
238 : }
239 859 : typename CallSiteTy::arg_iterator deopt_end() const {
240 859 : auto I = deopt_begin() + getNumTotalVMSArgs();
241 : assert((getCallSite().arg_end() - I) >= 0);
242 859 : return I;
243 : }
244 :
245 : /// range adapter for vm state arguments
246 : iterator_range<arg_iterator> deopt_operands() const {
247 : return make_range(deopt_begin(), deopt_end());
248 : }
249 :
250 : typename CallSiteTy::arg_iterator gc_args_begin() const {
251 792 : return deopt_end();
252 : }
253 : typename CallSiteTy::arg_iterator gc_args_end() const {
254 379 : return getCallSite().arg_end();
255 : }
256 :
257 346 : unsigned gcArgsStartIdx() const {
258 346 : return gc_args_begin() - getInstruction()->op_begin();
259 : }
260 :
261 : /// range adapter for gc arguments
262 : iterator_range<arg_iterator> gc_args() const {
263 : return make_range(gc_args_begin(), gc_args_end());
264 : }
265 :
266 : /// Get list of all gc reloactes linked to this statepoint
267 : /// May contain several relocations for the same base/derived pair.
268 : /// For example this could happen due to relocations on unwinding
269 : /// path of invoke.
270 : std::vector<const GCRelocateInst *> getRelocates() const;
271 :
272 : /// Get the experimental_gc_result call tied to this statepoint. Can be
273 : /// nullptr if there isn't a gc_result tied to this statepoint. Guaranteed to
274 : /// be a CallInst if non-null.
275 67 : const GCResultInst *getGCResult() const {
276 122 : for (auto *U : getInstruction()->users())
277 : if (auto *GRI = dyn_cast<GCResultInst>(U))
278 : return GRI;
279 : return nullptr;
280 : }
281 :
282 : #ifndef NDEBUG
283 : /// Asserts if this statepoint is malformed. Common cases for failure
284 : /// include incorrect length prefixes for variable length sections or
285 : /// illegal values for parameters.
286 : void verify() {
287 : assert(getNumCallArgs() >= 0 &&
288 : "number of arguments to actually callee can't be negative");
289 :
290 : // The internal asserts in the iterator accessors do the rest.
291 : (void)arg_begin();
292 : (void)arg_end();
293 : (void)gc_transition_args_begin();
294 : (void)gc_transition_args_end();
295 : (void)deopt_begin();
296 : (void)deopt_end();
297 : (void)gc_args_begin();
298 : (void)gc_args_end();
299 : }
300 : #endif
301 : };
302 :
303 : /// A specialization of it's base class for read only access
304 : /// to a gc.statepoint.
305 : class ImmutableStatepoint
306 : : public StatepointBase<const Function, const Instruction, const Value,
307 : ImmutableCallSite> {
308 : using Base =
309 : StatepointBase<const Function, const Instruction, const Value,
310 : ImmutableCallSite>;
311 :
312 : public:
313 69 : explicit ImmutableStatepoint(const Instruction *I) : Base(I) {}
314 : explicit ImmutableStatepoint(ImmutableCallSite CS) : Base(CS) {}
315 : };
316 :
317 : /// A specialization of it's base class for read-write access
318 : /// to a gc.statepoint.
319 : class Statepoint
320 : : public StatepointBase<Function, Instruction, Value, CallSite> {
321 : using Base = StatepointBase<Function, Instruction, Value, CallSite>;
322 :
323 : public:
324 312 : explicit Statepoint(Instruction *I) : Base(I) {}
325 : explicit Statepoint(CallSite CS) : Base(CS) {}
326 : };
327 :
328 : /// Common base class for representing values projected from a statepoint.
329 : /// Currently, the only projections available are gc.result and gc.relocate.
330 : class GCProjectionInst : public IntrinsicInst {
331 : public:
332 : static bool classof(const IntrinsicInst *I) {
333 : return I->getIntrinsicID() == Intrinsic::experimental_gc_relocate ||
334 : I->getIntrinsicID() == Intrinsic::experimental_gc_result;
335 : }
336 :
337 : static bool classof(const Value *V) {
338 : return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
339 : }
340 :
341 : /// Return true if this relocate is tied to the invoke statepoint.
342 : /// This includes relocates which are on the unwinding path.
343 : bool isTiedToInvoke() const {
344 : const Value *Token = getArgOperand(0);
345 :
346 : return isa<LandingPadInst>(Token) || isa<InvokeInst>(Token);
347 : }
348 :
349 : /// The statepoint with which this gc.relocate is associated.
350 4198 : const Instruction *getStatepoint() const {
351 4198 : const Value *Token = getArgOperand(0);
352 :
353 : // This takes care both of relocates for call statepoints and relocates
354 : // on normal path of invoke statepoint.
355 : if (!isa<LandingPadInst>(Token)) {
356 : assert(isStatepoint(Token));
357 : return cast<Instruction>(Token);
358 : }
359 :
360 : // This relocate is on exceptional path of an invoke statepoint
361 : const BasicBlock *InvokeBB =
362 395 : cast<Instruction>(Token)->getParent()->getUniquePredecessor();
363 :
364 : assert(InvokeBB && "safepoints should have unique landingpads");
365 : assert(InvokeBB->getTerminator() &&
366 : "safepoint block should be well formed");
367 : assert(isStatepoint(InvokeBB->getTerminator()));
368 :
369 395 : return InvokeBB->getTerminator();
370 : }
371 : };
372 :
373 : /// Represents calls to the gc.relocate intrinsic.
374 : class GCRelocateInst : public GCProjectionInst {
375 : public:
376 : static bool classof(const IntrinsicInst *I) {
377 : return I->getIntrinsicID() == Intrinsic::experimental_gc_relocate;
378 : }
379 :
380 : static bool classof(const Value *V) {
381 83617 : return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
382 : }
383 :
384 : /// The index into the associate statepoint's argument list
385 : /// which contains the base pointer of the pointer whose
386 : /// relocation this gc.relocate describes.
387 : unsigned getBasePtrIndex() const {
388 708 : return cast<ConstantInt>(getArgOperand(1))->getZExtValue();
389 : }
390 :
391 : /// The index into the associate statepoint's argument list which
392 : /// contains the pointer whose relocation this gc.relocate describes.
393 : unsigned getDerivedPtrIndex() const {
394 2875 : return cast<ConstantInt>(getArgOperand(2))->getZExtValue();
395 : }
396 :
397 576 : Value *getBasePtr() const {
398 576 : ImmutableCallSite CS(getStatepoint());
399 576 : return *(CS.arg_begin() + getBasePtrIndex());
400 : }
401 :
402 2725 : Value *getDerivedPtr() const {
403 2725 : ImmutableCallSite CS(getStatepoint());
404 2725 : return *(CS.arg_begin() + getDerivedPtrIndex());
405 : }
406 : };
407 :
408 : /// Represents calls to the gc.result intrinsic.
409 : class GCResultInst : public GCProjectionInst {
410 : public:
411 : static bool classof(const IntrinsicInst *I) {
412 : return I->getIntrinsicID() == Intrinsic::experimental_gc_result;
413 : }
414 :
415 : static bool classof(const Value *V) {
416 995 : return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
417 : }
418 : };
419 :
420 : template <typename FunTy, typename InstructionTy, typename ValueTy,
421 : typename CallSiteTy>
422 : std::vector<const GCRelocateInst *>
423 67 : StatepointBase<FunTy, InstructionTy, ValueTy, CallSiteTy>::getRelocates()
424 : const {
425 :
426 : std::vector<const GCRelocateInst *> Result;
427 :
428 : CallSiteTy StatepointCS = getCallSite();
429 :
430 : // Search for relocated pointers. Note that working backwards from the
431 : // gc_relocates ensures that we only get pairs which are actually relocated
432 : // and used after the statepoint.
433 149 : for (const User *U : getInstruction()->users())
434 82 : if (auto *Relocate = dyn_cast<GCRelocateInst>(U))
435 58 : Result.push_back(Relocate);
436 :
437 : if (!StatepointCS.isInvoke())
438 : return Result;
439 :
440 : // We need to scan thorough exceptional relocations if it is invoke statepoint
441 8 : LandingPadInst *LandingPad =
442 : cast<InvokeInst>(getInstruction())->getLandingPadInst();
443 :
444 : // Search for gc relocates that are attached to this landingpad.
445 16 : for (const User *LandingPadUser : LandingPad->users()) {
446 8 : if (auto *Relocate = dyn_cast<GCRelocateInst>(LandingPadUser))
447 8 : Result.push_back(Relocate);
448 : }
449 : return Result;
450 : }
451 :
452 : /// Call sites that get wrapped by a gc.statepoint (currently only in
453 : /// RewriteStatepointsForGC and potentially in other passes in the future) can
454 : /// have attributes that describe properties of gc.statepoint call they will be
455 : /// eventually be wrapped in. This struct is used represent such directives.
456 3 : struct StatepointDirectives {
457 : Optional<uint32_t> NumPatchBytes;
458 : Optional<uint64_t> StatepointID;
459 :
460 : static const uint64_t DefaultStatepointID = 0xABCDEF00;
461 : static const uint64_t DeoptBundleStatepointID = 0xABCDEF0F;
462 : };
463 :
464 : /// Parse out statepoint directives from the function attributes present in \p
465 : /// AS.
466 : StatepointDirectives parseStatepointDirectivesFromAttrs(AttributeList AS);
467 :
468 : /// Return \c true if the \p Attr is an attribute that is a statepoint
469 : /// directive.
470 : bool isStatepointDirectiveAttr(Attribute Attr);
471 :
472 : } // end namespace llvm
473 :
474 : #endif // LLVM_IR_STATEPOINT_H
|