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/CallSite.h"
21 #include "llvm/IR/Instructions.h"
22 #include "llvm/IR/Intrinsics.h"
23 #include "llvm/Support/Compiler.h"
27 bool isStatepoint(const ImmutableCallSite
&CS
);
28 bool isStatepoint(const Instruction
*inst
);
29 bool isStatepoint(const Instruction
&inst
);
31 bool isGCRelocate(const Instruction
*inst
);
32 bool isGCRelocate(const ImmutableCallSite
&CS
);
34 bool isGCResult(const Instruction
*inst
);
35 bool isGCResult(const ImmutableCallSite
&CS
);
37 /// Analogous to CallSiteBase, this provides most of the actual
38 /// functionality for Statepoint and ImmutableStatepoint. It is
39 /// templatized to allow easily specializing of const and non-const
40 /// concrete subtypes. This is structured analogous to CallSite
41 /// rather than the IntrinsicInst.h helpers since we want to support
42 /// invokable statepoints in the near future.
43 /// TODO: This does not currently allow the if(Statepoint S = ...)
44 /// idiom used with CallSites. Consider refactoring to support.
45 template <typename InstructionTy
, typename ValueTy
, typename CallSiteTy
>
46 class StatepointBase
{
47 CallSiteTy StatepointCS
;
48 void *operator new(size_t, unsigned) LLVM_DELETED_FUNCTION
;
49 void *operator new(size_t s
) LLVM_DELETED_FUNCTION
;
52 explicit StatepointBase(InstructionTy
*I
) : StatepointCS(I
) {
53 assert(isStatepoint(I
));
55 explicit StatepointBase(CallSiteTy CS
) : StatepointCS(CS
) {
56 assert(isStatepoint(CS
));
60 typedef typename
CallSiteTy::arg_iterator arg_iterator
;
62 /// Return the underlying CallSite.
63 CallSiteTy
getCallSite() {
67 /// Return the value actually being called or invoked.
68 ValueTy
*actualCallee() {
69 return StatepointCS
.getArgument(0);
71 /// Number of arguments to be passed to the actual callee.
73 return cast
<ConstantInt
>(StatepointCS
.getArgument(1))->getZExtValue();
75 /// Number of additional arguments excluding those intended
76 /// for garbage collection.
77 int numTotalVMSArgs() {
78 return cast
<ConstantInt
>(StatepointCS
.getArgument(3 + numCallArgs()))->getZExtValue();
81 typename
CallSiteTy::arg_iterator
call_args_begin() {
82 // 3 = callTarget, #callArgs, flag
84 assert(Offset
<= (int)StatepointCS
.arg_size());
85 return StatepointCS
.arg_begin() + Offset
;
87 typename
CallSiteTy::arg_iterator
call_args_end() {
88 int Offset
= 3 + numCallArgs();
89 assert(Offset
<= (int)StatepointCS
.arg_size());
90 return StatepointCS
.arg_begin() + Offset
;
93 /// range adapter for call arguments
94 iterator_range
<arg_iterator
> call_args() {
95 return iterator_range
<arg_iterator
>(call_args_begin(), call_args_end());
98 typename
CallSiteTy::arg_iterator
vm_state_begin() {
99 return call_args_end();
101 typename
CallSiteTy::arg_iterator
vm_state_end() {
102 int Offset
= 3 + numCallArgs() + 1 + numTotalVMSArgs();
103 assert(Offset
<= (int)StatepointCS
.arg_size());
104 return StatepointCS
.arg_begin() + Offset
;
107 /// range adapter for vm state arguments
108 iterator_range
<arg_iterator
> vm_state_args() {
109 return iterator_range
<arg_iterator
>(vm_state_begin(), vm_state_end());
112 typename
CallSiteTy::arg_iterator
first_vm_state_stack_begin() {
113 // 6 = numTotalVMSArgs, 1st_objectID, 1st_bci,
114 // 1st_#stack, 1st_#local, 1st_#monitor
115 return vm_state_begin() + 6;
118 typename
CallSiteTy::arg_iterator
gc_args_begin() {
119 return vm_state_end();
121 typename
CallSiteTy::arg_iterator
gc_args_end() {
122 return StatepointCS
.arg_end();
125 /// range adapter for gc arguments
126 iterator_range
<arg_iterator
> gc_args() {
127 return iterator_range
<arg_iterator
>(gc_args_begin(), gc_args_end());
132 /// Asserts if this statepoint is malformed. Common cases for failure
133 /// include incorrect length prefixes for variable length sections or
134 /// illegal values for parameters.
136 assert(numCallArgs() >= 0 &&
137 "number of arguments to actually callee can't be negative");
139 // The internal asserts in the iterator accessors do the rest.
140 (void)call_args_begin();
141 (void)call_args_end();
142 (void)vm_state_begin();
143 (void)vm_state_end();
144 (void)gc_args_begin();
150 /// A specialization of it's base class for read only access
151 /// to a gc.statepoint.
152 class ImmutableStatepoint
153 : public StatepointBase
<const Instruction
, const Value
,
155 typedef StatepointBase
<const Instruction
, const Value
, ImmutableCallSite
>
159 explicit ImmutableStatepoint(const Instruction
*I
) : Base(I
) {}
160 explicit ImmutableStatepoint(ImmutableCallSite CS
) : Base(CS
) {}
163 /// A specialization of it's base class for read-write access
164 /// to a gc.statepoint.
165 class Statepoint
: public StatepointBase
<Instruction
, Value
, CallSite
> {
166 typedef StatepointBase
<Instruction
, Value
, CallSite
> Base
;
169 explicit Statepoint(Instruction
*I
) : Base(I
) {}
170 explicit Statepoint(CallSite CS
) : Base(CS
) {}
173 /// Wraps a call to a gc.relocate and provides access to it's operands.
174 /// TODO: This should likely be refactored to resememble the wrappers in
175 /// InstrinsicInst.h.
176 class GCRelocateOperands
{
177 ImmutableCallSite RelocateCS
;
180 GCRelocateOperands(const User
* U
) : RelocateCS(U
) {
181 assert(isGCRelocate(U
));
183 GCRelocateOperands(const Instruction
*inst
) : RelocateCS(inst
) {
184 assert(isGCRelocate(inst
));
186 GCRelocateOperands(CallSite CS
) : RelocateCS(CS
) {
187 assert(isGCRelocate(CS
));
190 /// The statepoint with which this gc.relocate is associated.
191 const Instruction
*statepoint() {
192 return cast
<Instruction
>(RelocateCS
.getArgument(0));
194 /// The index into the associate statepoint's argument list
195 /// which contains the base pointer of the pointer whose
196 /// relocation this gc.relocate describes.
198 return cast
<ConstantInt
>(RelocateCS
.getArgument(1))->getZExtValue();
200 /// The index into the associate statepoint's argument list which
201 /// contains the pointer whose relocation this gc.relocate describes.
202 int derivedPtrIndex() {
203 return cast
<ConstantInt
>(RelocateCS
.getArgument(2))->getZExtValue();
206 ImmutableCallSite
CS(statepoint());
207 return *(CS
.arg_begin() + basePtrIndex());
209 Value
*derivedPtr() {
210 ImmutableCallSite
CS(statepoint());
211 return *(CS
.arg_begin() + derivedPtrIndex());