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, and 12 // gc.result intrinsics 13 // 14 //===----------------------------------------------------------------------===// 15 16 #ifndef __LLVM_IR_STATEPOINT_H 17 #define __LLVM_IR_STATEPOINT_H 18 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" 24 25 namespace llvm { 26 27 bool isStatepoint(const ImmutableCallSite &CS); 28 bool isStatepoint(const Instruction *inst); 29 bool isStatepoint(const Instruction &inst); 30 31 bool isGCRelocate(const Instruction *inst); 32 bool isGCRelocate(const ImmutableCallSite &CS); 33 34 bool isGCResult(const Instruction *inst); 35 bool isGCResult(const ImmutableCallSite &CS); 36 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; 50 51 protected: StatepointBase(InstructionTy * I)52 explicit StatepointBase(InstructionTy *I) : StatepointCS(I) { 53 assert(isStatepoint(I)); 54 } StatepointBase(CallSiteTy CS)55 explicit StatepointBase(CallSiteTy CS) : StatepointCS(CS) { 56 assert(isStatepoint(CS)); 57 } 58 59 public: 60 typedef typename CallSiteTy::arg_iterator arg_iterator; 61 62 /// Return the underlying CallSite. getCallSite()63 CallSiteTy getCallSite() { 64 return StatepointCS; 65 } 66 67 /// Return the value actually being called or invoked. actualCallee()68 ValueTy *actualCallee() { 69 return StatepointCS.getArgument(0); 70 } 71 /// Number of arguments to be passed to the actual callee. numCallArgs()72 int numCallArgs() { 73 return cast<ConstantInt>(StatepointCS.getArgument(1))->getZExtValue(); 74 } 75 /// Number of additional arguments excluding those intended 76 /// for garbage collection. numTotalVMSArgs()77 int numTotalVMSArgs() { 78 return cast<ConstantInt>(StatepointCS.getArgument(3 + numCallArgs()))->getZExtValue(); 79 } 80 call_args_begin()81 typename CallSiteTy::arg_iterator call_args_begin() { 82 // 3 = callTarget, #callArgs, flag 83 int Offset = 3; 84 assert(Offset <= (int)StatepointCS.arg_size()); 85 return StatepointCS.arg_begin() + Offset; 86 } call_args_end()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; 91 } 92 93 /// range adapter for call arguments call_args()94 iterator_range<arg_iterator> call_args() { 95 return iterator_range<arg_iterator>(call_args_begin(), call_args_end()); 96 } 97 vm_state_begin()98 typename CallSiteTy::arg_iterator vm_state_begin() { 99 return call_args_end(); 100 } vm_state_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; 105 } 106 107 /// range adapter for vm state arguments vm_state_args()108 iterator_range<arg_iterator> vm_state_args() { 109 return iterator_range<arg_iterator>(vm_state_begin(), vm_state_end()); 110 } 111 first_vm_state_stack_begin()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; 116 } 117 gc_args_begin()118 typename CallSiteTy::arg_iterator gc_args_begin() { 119 return vm_state_end(); 120 } gc_args_end()121 typename CallSiteTy::arg_iterator gc_args_end() { 122 return StatepointCS.arg_end(); 123 } 124 125 /// range adapter for gc arguments gc_args()126 iterator_range<arg_iterator> gc_args() { 127 return iterator_range<arg_iterator>(gc_args_begin(), gc_args_end()); 128 } 129 130 131 #ifndef NDEBUG 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. verify()135 void verify() { 136 assert(numCallArgs() >= 0 && 137 "number of arguments to actually callee can't be negative"); 138 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(); 145 (void)gc_args_end(); 146 } 147 #endif 148 }; 149 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, 154 ImmutableCallSite> { 155 typedef StatepointBase<const Instruction, const Value, ImmutableCallSite> 156 Base; 157 158 public: ImmutableStatepoint(const Instruction * I)159 explicit ImmutableStatepoint(const Instruction *I) : Base(I) {} ImmutableStatepoint(ImmutableCallSite CS)160 explicit ImmutableStatepoint(ImmutableCallSite CS) : Base(CS) {} 161 }; 162 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; 167 168 public: Statepoint(Instruction * I)169 explicit Statepoint(Instruction *I) : Base(I) {} Statepoint(CallSite CS)170 explicit Statepoint(CallSite CS) : Base(CS) {} 171 }; 172 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; 178 179 public: GCRelocateOperands(const User * U)180 GCRelocateOperands(const User* U) : RelocateCS(U) { 181 assert(isGCRelocate(U)); 182 } GCRelocateOperands(const Instruction * inst)183 GCRelocateOperands(const Instruction *inst) : RelocateCS(inst) { 184 assert(isGCRelocate(inst)); 185 } GCRelocateOperands(CallSite CS)186 GCRelocateOperands(CallSite CS) : RelocateCS(CS) { 187 assert(isGCRelocate(CS)); 188 } 189 190 /// The statepoint with which this gc.relocate is associated. statepoint()191 const Instruction *statepoint() { 192 return cast<Instruction>(RelocateCS.getArgument(0)); 193 } 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. basePtrIndex()197 int basePtrIndex() { 198 return cast<ConstantInt>(RelocateCS.getArgument(1))->getZExtValue(); 199 } 200 /// The index into the associate statepoint's argument list which 201 /// contains the pointer whose relocation this gc.relocate describes. derivedPtrIndex()202 int derivedPtrIndex() { 203 return cast<ConstantInt>(RelocateCS.getArgument(2))->getZExtValue(); 204 } basePtr()205 Value *basePtr() { 206 ImmutableCallSite CS(statepoint()); 207 return *(CS.arg_begin() + basePtrIndex()); 208 } derivedPtr()209 Value *derivedPtr() { 210 ImmutableCallSite CS(statepoint()); 211 return *(CS.arg_begin() + derivedPtrIndex()); 212 } 213 }; 214 } 215 #endif 216