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/Instructions.h"
23 #include "llvm/IR/Intrinsics.h"
24 #include "llvm/Support/Compiler.h"
28 class GCRelocateOperands;
29 class ImmutableStatepoint;
31 bool isStatepoint(const ImmutableCallSite &CS);
32 bool isStatepoint(const Value *inst);
33 bool isStatepoint(const Value &inst);
35 bool isGCRelocate(const Value *inst);
36 bool isGCRelocate(const ImmutableCallSite &CS);
38 bool isGCResult(const Value *inst);
39 bool isGCResult(const ImmutableCallSite &CS);
41 /// Analogous to CallSiteBase, this provides most of the actual
42 /// functionality for Statepoint and ImmutableStatepoint. It is
43 /// templatized to allow easily specializing of const and non-const
44 /// concrete subtypes. This is structured analogous to CallSite
45 /// rather than the IntrinsicInst.h helpers since we want to support
46 /// invokable statepoints in the near future.
47 /// TODO: This does not currently allow the if(Statepoint S = ...)
48 /// idiom used with CallSites. Consider refactoring to support.
49 template <typename InstructionTy, typename ValueTy, typename CallSiteTy>
50 class StatepointBase {
51 CallSiteTy StatepointCS;
52 void *operator new(size_t, unsigned) = delete;
53 void *operator new(size_t s) = delete;
56 explicit StatepointBase(InstructionTy *I) : StatepointCS(I) {
57 assert(isStatepoint(I));
59 explicit StatepointBase(CallSiteTy CS) : StatepointCS(CS) {
60 assert(isStatepoint(CS));
64 typedef typename CallSiteTy::arg_iterator arg_iterator;
66 /// Return the underlying CallSite.
67 CallSiteTy getCallSite() {
71 /// Return the value actually being called or invoked.
72 ValueTy *getActualCallee() { return StatepointCS.getArgument(0); }
74 /// Return the type of the value returned by the call underlying the
76 Type *getActualReturnType() {
77 auto *FTy = cast<FunctionType>(
78 cast<PointerType>(getActualCallee()->getType())->getElementType());
79 return FTy->getReturnType();
82 /// Number of arguments to be passed to the actual callee.
83 int getNumCallArgs() {
84 return cast<ConstantInt>(StatepointCS.getArgument(1))->getZExtValue();
87 /// Number of additional arguments excluding those intended
88 /// for garbage collection.
89 int getNumTotalVMSArgs() {
90 const Value *NumVMSArgs = StatepointCS.getArgument(3 + getNumCallArgs());
91 return cast<ConstantInt>(NumVMSArgs)->getZExtValue();
94 int callArgsBeginOffset() { return 3; }
96 typename CallSiteTy::arg_iterator call_args_begin() {
97 // 3 = callTarget, #callArgs, flag
98 int Offset = callArgsBeginOffset();
99 assert(Offset <= (int)StatepointCS.arg_size());
100 return StatepointCS.arg_begin() + Offset;
102 typename CallSiteTy::arg_iterator call_args_end() {
103 int Offset = callArgsBeginOffset() + getNumCallArgs();
104 assert(Offset <= (int)StatepointCS.arg_size());
105 return StatepointCS.arg_begin() + Offset;
108 /// range adapter for call arguments
109 iterator_range<arg_iterator> call_args() {
110 return iterator_range<arg_iterator>(call_args_begin(), call_args_end());
113 typename CallSiteTy::arg_iterator vm_state_begin() {
114 return call_args_end();
116 typename CallSiteTy::arg_iterator vm_state_end() {
117 int Offset = 3 + getNumCallArgs() + 1 + getNumTotalVMSArgs();
118 assert(Offset <= (int)StatepointCS.arg_size());
119 return StatepointCS.arg_begin() + Offset;
122 /// range adapter for vm state arguments
123 iterator_range<arg_iterator> vm_state_args() {
124 return iterator_range<arg_iterator>(vm_state_begin(), vm_state_end());
127 typename CallSiteTy::arg_iterator first_vm_state_stack_begin() {
128 // 6 = numTotalVMSArgs, 1st_objectID, 1st_bci,
129 // 1st_#stack, 1st_#local, 1st_#monitor
130 return vm_state_begin() + 6;
133 typename CallSiteTy::arg_iterator gc_args_begin() {
134 return vm_state_end();
136 typename CallSiteTy::arg_iterator gc_args_end() {
137 return StatepointCS.arg_end();
140 /// range adapter for gc arguments
141 iterator_range<arg_iterator> gc_args() {
142 return iterator_range<arg_iterator>(gc_args_begin(), gc_args_end());
145 /// Get list of all gc reloactes linked to this statepoint
146 /// May contain several relocations for the same base/derived pair.
147 /// For example this could happen due to relocations on unwinding
149 std::vector<GCRelocateOperands> getRelocates(ImmutableStatepoint &IS);
152 /// Asserts if this statepoint is malformed. Common cases for failure
153 /// include incorrect length prefixes for variable length sections or
154 /// illegal values for parameters.
156 assert(getNumCallArgs() >= 0 &&
157 "number of arguments to actually callee can't be negative");
159 // The internal asserts in the iterator accessors do the rest.
160 (void)call_args_begin();
161 (void)call_args_end();
162 (void)vm_state_begin();
163 (void)vm_state_end();
164 (void)gc_args_begin();
170 /// A specialization of it's base class for read only access
171 /// to a gc.statepoint.
172 class ImmutableStatepoint
173 : public StatepointBase<const Instruction, const Value,
175 typedef StatepointBase<const Instruction, const Value, ImmutableCallSite>
179 explicit ImmutableStatepoint(const Instruction *I) : Base(I) {}
180 explicit ImmutableStatepoint(ImmutableCallSite CS) : Base(CS) {}
183 /// A specialization of it's base class for read-write access
184 /// to a gc.statepoint.
185 class Statepoint : public StatepointBase<Instruction, Value, CallSite> {
186 typedef StatepointBase<Instruction, Value, CallSite> Base;
189 explicit Statepoint(Instruction *I) : Base(I) {}
190 explicit Statepoint(CallSite CS) : Base(CS) {}
193 /// Wraps a call to a gc.relocate and provides access to it's operands.
194 /// TODO: This should likely be refactored to resememble the wrappers in
195 /// InstrinsicInst.h.
196 class GCRelocateOperands {
197 ImmutableCallSite RelocateCS;
200 GCRelocateOperands(const User* U) : RelocateCS(U) {
201 assert(isGCRelocate(U));
203 GCRelocateOperands(const Instruction *inst) : RelocateCS(inst) {
204 assert(isGCRelocate(inst));
206 GCRelocateOperands(CallSite CS) : RelocateCS(CS) {
207 assert(isGCRelocate(CS));
210 /// Return true if this relocate is tied to the invoke statepoint.
211 /// This includes relocates which are on the unwinding path.
212 bool isTiedToInvoke() const {
213 const Value *Token = RelocateCS.getArgument(0);
215 return isa<ExtractValueInst>(Token) ||
216 isa<InvokeInst>(Token);
219 /// Get enclosed relocate intrinsic
220 ImmutableCallSite getUnderlyingCallSite() {
224 /// The statepoint with which this gc.relocate is associated.
225 const Instruction *getStatepoint() {
226 const Value *Token = RelocateCS.getArgument(0);
228 // This takes care both of relocates for call statepoints and relocates
229 // on normal path of invoke statepoint.
230 if (!isa<ExtractValueInst>(Token)) {
231 return cast<Instruction>(Token);
234 // This relocate is on exceptional path of an invoke statepoint
235 const BasicBlock *InvokeBB =
236 cast<Instruction>(Token)->getParent()->getUniquePredecessor();
238 assert(InvokeBB && "safepoints should have unique landingpads");
239 assert(InvokeBB->getTerminator() &&
240 "safepoint block should be well formed");
241 assert(isStatepoint(InvokeBB->getTerminator()));
243 return InvokeBB->getTerminator();
246 /// The index into the associate statepoint's argument list
247 /// which contains the base pointer of the pointer whose
248 /// relocation this gc.relocate describes.
249 unsigned getBasePtrIndex() {
250 return cast<ConstantInt>(RelocateCS.getArgument(1))->getZExtValue();
253 /// The index into the associate statepoint's argument list which
254 /// contains the pointer whose relocation this gc.relocate describes.
255 unsigned getDerivedPtrIndex() {
256 return cast<ConstantInt>(RelocateCS.getArgument(2))->getZExtValue();
259 Value *getBasePtr() {
260 ImmutableCallSite CS(getStatepoint());
261 return *(CS.arg_begin() + getBasePtrIndex());
264 Value *getDerivedPtr() {
265 ImmutableCallSite CS(getStatepoint());
266 return *(CS.arg_begin() + getDerivedPtrIndex());
270 template <typename InstructionTy, typename ValueTy, typename CallSiteTy>
271 std::vector<GCRelocateOperands>
272 StatepointBase<InstructionTy, ValueTy, CallSiteTy>::
273 getRelocates(ImmutableStatepoint &IS) {
275 std::vector<GCRelocateOperands> Result;
277 ImmutableCallSite StatepointCS = IS.getCallSite();
279 // Search for relocated pointers. Note that working backwards from the
280 // gc_relocates ensures that we only get pairs which are actually relocated
281 // and used after the statepoint.
282 for (const User *U : StatepointCS.getInstruction()->users())
284 Result.push_back(GCRelocateOperands(U));
286 if (!StatepointCS.isInvoke())
289 // We need to scan thorough exceptional relocations if it is invoke statepoint
290 LandingPadInst *LandingPad =
291 cast<InvokeInst>(StatepointCS.getInstruction())->getLandingPadInst();
293 // Search for extract value from landingpad instruction to which
294 // gc relocates will be attached
295 for (const User *LandingPadUser : LandingPad->users()) {
296 if (!isa<ExtractValueInst>(LandingPadUser))
299 // gc relocates should be attached to this extract value
300 for (const User *U : LandingPadUser->users())
302 Result.push_back(GCRelocateOperands(U));