1 //===-- llvm/IR/Statepoint.h - gc.statepoint utilities ------ --*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This file contains utility functions and a wrapper class analogous to
11 // CallSite for accessing the fields of gc.statepoint, gc.relocate, and
12 // gc.result intrinsics
14 //===----------------------------------------------------------------------===//
16 #ifndef LLVM_IR_STATEPOINT_H
17 #define LLVM_IR_STATEPOINT_H
19 #include "llvm/ADT/iterator_range.h"
20 #include "llvm/IR/BasicBlock.h"
21 #include "llvm/IR/CallSite.h"
22 #include "llvm/IR/Constants.h"
23 #include "llvm/IR/Instructions.h"
24 #include "llvm/IR/Intrinsics.h"
25 #include "llvm/Support/Compiler.h"
28 /// The statepoint intrinsic accepts a set of flags as its third argument.
29 /// Valid values come out of this set.
30 enum class StatepointFlags {
32 GCTransition = 1, ///< Indicates that this statepoint is a transition from
33 ///< GC-aware code to code that is not GC-aware.
35 MaskAll = GCTransition ///< A bitmask that includes all valid flags.
38 class GCRelocateOperands;
39 class ImmutableStatepoint;
41 bool isStatepoint(const ImmutableCallSite &CS);
42 bool isStatepoint(const Value *inst);
43 bool isStatepoint(const Value &inst);
45 bool isGCRelocate(const Value *inst);
46 bool isGCRelocate(const ImmutableCallSite &CS);
48 bool isGCResult(const Value *inst);
49 bool isGCResult(const ImmutableCallSite &CS);
51 /// Analogous to CallSiteBase, this provides most of the actual
52 /// functionality for Statepoint and ImmutableStatepoint. It is
53 /// templatized to allow easily specializing of const and non-const
54 /// concrete subtypes. This is structured analogous to CallSite
55 /// rather than the IntrinsicInst.h helpers since we want to support
56 /// invokable statepoints in the near future.
57 /// TODO: This does not currently allow the if(Statepoint S = ...)
58 /// idiom used with CallSites. Consider refactoring to support.
59 template <typename InstructionTy, typename ValueTy, typename CallSiteTy>
60 class StatepointBase {
61 CallSiteTy StatepointCS;
62 void *operator new(size_t, unsigned) = delete;
63 void *operator new(size_t s) = delete;
66 explicit StatepointBase(InstructionTy *I) : StatepointCS(I) {
67 assert(isStatepoint(I));
69 explicit StatepointBase(CallSiteTy CS) : StatepointCS(CS) {
70 assert(isStatepoint(CS));
74 typedef typename CallSiteTy::arg_iterator arg_iterator;
85 /// Return the underlying CallSite.
86 CallSiteTy getCallSite() { return StatepointCS; }
88 uint64_t getFlags() const {
89 return cast<ConstantInt>(StatepointCS.getArgument(FlagsPos))
93 /// Return the ID associated with this statepoint.
95 const Value *IDVal = StatepointCS.getArgument(IDPos);
96 return cast<ConstantInt>(IDVal)->getZExtValue();
99 /// Return the number of patchable bytes associated with this statepoint.
100 uint32_t getNumPatchBytes() {
101 const Value *NumPatchBytesVal = StatepointCS.getArgument(NumPatchBytesPos);
102 uint64_t NumPatchBytes =
103 cast<ConstantInt>(NumPatchBytesVal)->getZExtValue();
104 assert(isInt<32>(NumPatchBytes) && "should fit in 32 bits!");
105 return NumPatchBytes;
108 /// Return the value actually being called or invoked.
109 ValueTy *getActualCallee() {
110 return StatepointCS.getArgument(ActualCalleePos);
113 /// Return the type of the value returned by the call underlying the
115 Type *getActualReturnType() {
116 auto *FTy = cast<FunctionType>(
117 cast<PointerType>(getActualCallee()->getType())->getElementType());
118 return FTy->getReturnType();
121 /// Number of arguments to be passed to the actual callee.
122 int getNumCallArgs() {
123 const Value *NumCallArgsVal = StatepointCS.getArgument(NumCallArgsPos);
124 return cast<ConstantInt>(NumCallArgsVal)->getZExtValue();
127 typename CallSiteTy::arg_iterator call_args_begin() {
128 assert(CallArgsBeginPos <= (int)StatepointCS.arg_size());
129 return StatepointCS.arg_begin() + CallArgsBeginPos;
131 typename CallSiteTy::arg_iterator call_args_end() {
132 auto I = call_args_begin() + getNumCallArgs();
133 assert((StatepointCS.arg_end() - I) >= 0);
137 /// range adapter for call arguments
138 iterator_range<arg_iterator> call_args() {
139 return iterator_range<arg_iterator>(call_args_begin(), call_args_end());
142 /// Number of GC transition args.
143 int getNumTotalGCTransitionArgs() {
144 const Value *NumGCTransitionArgs = *call_args_end();
145 return cast<ConstantInt>(NumGCTransitionArgs)->getZExtValue();
147 typename CallSiteTy::arg_iterator gc_transition_args_begin() {
148 auto I = call_args_end() + 1;
149 assert((StatepointCS.arg_end() - I) >= 0);
152 typename CallSiteTy::arg_iterator gc_transition_args_end() {
153 auto I = gc_transition_args_begin() + getNumTotalGCTransitionArgs();
154 assert((StatepointCS.arg_end() - I) >= 0);
158 /// range adapter for GC transition arguments
159 iterator_range<arg_iterator> gc_transition_args() {
160 return iterator_range<arg_iterator>(gc_transition_args_begin(),
161 gc_transition_args_end());
164 /// Number of additional arguments excluding those intended
165 /// for garbage collection.
166 int getNumTotalVMSArgs() {
167 const Value *NumVMSArgs = *gc_transition_args_end();
168 return cast<ConstantInt>(NumVMSArgs)->getZExtValue();
171 typename CallSiteTy::arg_iterator vm_state_begin() {
172 auto I = gc_transition_args_end() + 1;
173 assert((StatepointCS.arg_end() - I) >= 0);
176 typename CallSiteTy::arg_iterator vm_state_end() {
177 auto I = vm_state_begin() + getNumTotalVMSArgs();
178 assert((StatepointCS.arg_end() - I) >= 0);
182 /// range adapter for vm state arguments
183 iterator_range<arg_iterator> vm_state_args() {
184 return iterator_range<arg_iterator>(vm_state_begin(), vm_state_end());
187 typename CallSiteTy::arg_iterator gc_args_begin() { return vm_state_end(); }
188 typename CallSiteTy::arg_iterator gc_args_end() {
189 return StatepointCS.arg_end();
192 /// range adapter for gc arguments
193 iterator_range<arg_iterator> gc_args() {
194 return iterator_range<arg_iterator>(gc_args_begin(), gc_args_end());
197 /// Get list of all gc reloactes linked to this statepoint
198 /// May contain several relocations for the same base/derived pair.
199 /// For example this could happen due to relocations on unwinding
201 std::vector<GCRelocateOperands> getRelocates();
204 /// Asserts if this statepoint is malformed. Common cases for failure
205 /// include incorrect length prefixes for variable length sections or
206 /// illegal values for parameters.
208 assert(getNumCallArgs() >= 0 &&
209 "number of arguments to actually callee can't be negative");
211 // The internal asserts in the iterator accessors do the rest.
212 (void)call_args_begin();
213 (void)call_args_end();
214 (void)gc_transition_args_begin();
215 (void)gc_transition_args_end();
216 (void)vm_state_begin();
217 (void)vm_state_end();
218 (void)gc_args_begin();
224 /// A specialization of it's base class for read only access
225 /// to a gc.statepoint.
226 class ImmutableStatepoint
227 : public StatepointBase<const Instruction, const Value, ImmutableCallSite> {
228 typedef StatepointBase<const Instruction, const Value, ImmutableCallSite>
232 explicit ImmutableStatepoint(const Instruction *I) : Base(I) {}
233 explicit ImmutableStatepoint(ImmutableCallSite CS) : Base(CS) {}
236 /// A specialization of it's base class for read-write access
237 /// to a gc.statepoint.
238 class Statepoint : public StatepointBase<Instruction, Value, CallSite> {
239 typedef StatepointBase<Instruction, Value, CallSite> Base;
242 explicit Statepoint(Instruction *I) : Base(I) {}
243 explicit Statepoint(CallSite CS) : Base(CS) {}
246 /// Wraps a call to a gc.relocate and provides access to it's operands.
247 /// TODO: This should likely be refactored to resememble the wrappers in
248 /// InstrinsicInst.h.
249 class GCRelocateOperands {
250 ImmutableCallSite RelocateCS;
253 GCRelocateOperands(const User *U) : RelocateCS(U) { assert(isGCRelocate(U)); }
254 GCRelocateOperands(const Instruction *inst) : RelocateCS(inst) {
255 assert(isGCRelocate(inst));
257 GCRelocateOperands(CallSite CS) : RelocateCS(CS) { assert(isGCRelocate(CS)); }
259 /// Return true if this relocate is tied to the invoke statepoint.
260 /// This includes relocates which are on the unwinding path.
261 bool isTiedToInvoke() const {
262 const Value *Token = RelocateCS.getArgument(0);
264 return isa<ExtractValueInst>(Token) || isa<InvokeInst>(Token);
267 /// Get enclosed relocate intrinsic
268 ImmutableCallSite getUnderlyingCallSite() { return RelocateCS; }
270 /// The statepoint with which this gc.relocate is associated.
271 const Instruction *getStatepoint() {
272 const Value *Token = RelocateCS.getArgument(0);
274 // This takes care both of relocates for call statepoints and relocates
275 // on normal path of invoke statepoint.
276 if (!isa<ExtractValueInst>(Token)) {
277 return cast<Instruction>(Token);
280 // This relocate is on exceptional path of an invoke statepoint
281 const BasicBlock *InvokeBB =
282 cast<Instruction>(Token)->getParent()->getUniquePredecessor();
284 assert(InvokeBB && "safepoints should have unique landingpads");
285 assert(InvokeBB->getTerminator() &&
286 "safepoint block should be well formed");
287 assert(isStatepoint(InvokeBB->getTerminator()));
289 return InvokeBB->getTerminator();
292 /// The index into the associate statepoint's argument list
293 /// which contains the base pointer of the pointer whose
294 /// relocation this gc.relocate describes.
295 unsigned getBasePtrIndex() {
296 return cast<ConstantInt>(RelocateCS.getArgument(1))->getZExtValue();
299 /// The index into the associate statepoint's argument list which
300 /// contains the pointer whose relocation this gc.relocate describes.
301 unsigned getDerivedPtrIndex() {
302 return cast<ConstantInt>(RelocateCS.getArgument(2))->getZExtValue();
305 Value *getBasePtr() {
306 ImmutableCallSite CS(getStatepoint());
307 return *(CS.arg_begin() + getBasePtrIndex());
310 Value *getDerivedPtr() {
311 ImmutableCallSite CS(getStatepoint());
312 return *(CS.arg_begin() + getDerivedPtrIndex());
316 template <typename InstructionTy, typename ValueTy, typename CallSiteTy>
317 std::vector<GCRelocateOperands>
318 StatepointBase<InstructionTy, ValueTy, CallSiteTy>::getRelocates() {
320 std::vector<GCRelocateOperands> Result;
322 CallSiteTy StatepointCS = getCallSite();
324 // Search for relocated pointers. Note that working backwards from the
325 // gc_relocates ensures that we only get pairs which are actually relocated
326 // and used after the statepoint.
327 for (const User *U : StatepointCS.getInstruction()->users())
329 Result.push_back(GCRelocateOperands(U));
331 if (!StatepointCS.isInvoke())
334 // We need to scan thorough exceptional relocations if it is invoke statepoint
335 LandingPadInst *LandingPad =
336 cast<InvokeInst>(StatepointCS.getInstruction())->getLandingPadInst();
338 // Search for extract value from landingpad instruction to which
339 // gc relocates will be attached
340 for (const User *LandingPadUser : LandingPad->users()) {
341 if (!isa<ExtractValueInst>(LandingPadUser))
344 // gc relocates should be attached to this extract value
345 for (const User *U : LandingPadUser->users())
347 Result.push_back(GCRelocateOperands(U));