1 //===- llvm/IR/Statepoint.h - gc.statepoint utilities -----------*- C++ -*-===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // This file contains utility functions and a wrapper class analogous to 10 // CallBase for accessing the fields of gc.statepoint, gc.relocate, 11 // gc.result intrinsics; and some general utilities helpful when dealing with 12 // gc.statepoint. 13 // 14 //===----------------------------------------------------------------------===// 15 16 #ifndef LLVM_IR_STATEPOINT_H 17 #define LLVM_IR_STATEPOINT_H 18 19 #include "llvm/ADT/Optional.h" 20 #include "llvm/ADT/iterator_range.h" 21 #include "llvm/IR/Attributes.h" 22 #include "llvm/IR/Constants.h" 23 #include "llvm/IR/Function.h" 24 #include "llvm/IR/InstrTypes.h" 25 #include "llvm/IR/Instructions.h" 26 #include "llvm/IR/IntrinsicInst.h" 27 #include "llvm/IR/Intrinsics.h" 28 #include "llvm/Support/Casting.h" 29 #include "llvm/Support/MathExtras.h" 30 #include <cassert> 31 #include <cstddef> 32 #include <cstdint> 33 #include <vector> 34 35 namespace llvm { 36 37 /// The statepoint intrinsic accepts a set of flags as its third argument. 38 /// Valid values come out of this set. 39 enum class StatepointFlags { 40 None = 0, 41 GCTransition = 1, ///< Indicates that this statepoint is a transition from 42 ///< GC-aware code to code that is not GC-aware. 43 /// Mark the deopt arguments associated with the statepoint as only being 44 /// "live-in". By default, deopt arguments are "live-through". "live-through" 45 /// requires that they the value be live on entry, on exit, and at any point 46 /// during the call. "live-in" only requires the value be available at the 47 /// start of the call. In particular, "live-in" values can be placed in 48 /// unused argument registers or other non-callee saved registers. 49 DeoptLiveIn = 2, 50 51 MaskAll = 3 ///< A bitmask that includes all valid flags. 52 }; 53 54 // These two are defined in IntrinsicInst since they're part of the 55 // IntrinsicInst class hierarchy. 56 class GCRelocateInst; 57 58 /// Represents a gc.statepoint intrinsic call. This extends directly from 59 /// CallBase as the IntrinsicInst only supports calls and gc.statepoint is 60 /// invokable. 61 class GCStatepointInst : public CallBase { 62 public: 63 GCStatepointInst() = delete; 64 GCStatepointInst(const GCStatepointInst &) = delete; 65 GCStatepointInst &operator=(const GCStatepointInst &) = delete; 66 67 static bool classof(const CallBase *I) { 68 if (const Function *CF = I->getCalledFunction()) 69 return CF->getIntrinsicID() == Intrinsic::experimental_gc_statepoint; 70 return false; 71 } 72 73 static bool classof(const Value *V) { 74 return isa<CallBase>(V) && classof(cast<CallBase>(V)); 75 } 76 77 enum { 78 IDPos = 0, 79 NumPatchBytesPos = 1, 80 CalledFunctionPos = 2, 81 NumCallArgsPos = 3, 82 FlagsPos = 4, 83 CallArgsBeginPos = 5, 84 }; 85 86 /// Return the ID associated with this statepoint. 87 uint64_t getID() const { 88 return cast<ConstantInt>(getArgOperand(IDPos))->getZExtValue(); 89 } 90 91 /// Return the number of patchable bytes associated with this statepoint. 92 uint32_t getNumPatchBytes() const { 93 const Value *NumPatchBytesVal = getArgOperand(NumPatchBytesPos); 94 uint64_t NumPatchBytes = 95 cast<ConstantInt>(NumPatchBytesVal)->getZExtValue(); 96 assert(isInt<32>(NumPatchBytes) && "should fit in 32 bits!"); 97 return NumPatchBytes; 98 } 99 100 /// Number of arguments to be passed to the actual callee. 101 int getNumCallArgs() const { 102 return cast<ConstantInt>(getArgOperand(NumCallArgsPos))->getZExtValue(); 103 } 104 105 uint64_t getFlags() const { 106 return cast<ConstantInt>(getArgOperand(FlagsPos))->getZExtValue(); 107 } 108 109 /// Return the value actually being called or invoked. 110 Value *getActualCalledOperand() const { 111 return getArgOperand(CalledFunctionPos); 112 } 113 114 /// Returns the function called if this is a wrapping a direct call, and null 115 /// otherwise. 116 Function *getActualCalledFunction() const { 117 return dyn_cast_or_null<Function>(getActualCalledOperand()); 118 } 119 120 /// Return the type of the value returned by the call underlying the 121 /// statepoint. 122 Type *getActualReturnType() const { 123 auto *FT = cast<FunctionType>(getParamElementType(CalledFunctionPos)); 124 return FT->getReturnType(); 125 } 126 127 128 /// Return the number of arguments to the underlying call. 129 size_t actual_arg_size() const { return getNumCallArgs(); } 130 /// Return an iterator to the begining of the arguments to the underlying call 131 const_op_iterator actual_arg_begin() const { 132 assert(CallArgsBeginPos <= (int)arg_size()); 133 return arg_begin() + CallArgsBeginPos; 134 } 135 /// Return an end iterator of the arguments to the underlying call 136 const_op_iterator actual_arg_end() const { 137 auto I = actual_arg_begin() + actual_arg_size(); 138 assert((arg_end() - I) == 2); 139 return I; 140 } 141 /// range adapter for actual call arguments 142 iterator_range<const_op_iterator> actual_args() const { 143 return make_range(actual_arg_begin(), actual_arg_end()); 144 } 145 146 const_op_iterator gc_transition_args_begin() const { 147 if (auto Opt = getOperandBundle(LLVMContext::OB_gc_transition)) 148 return Opt->Inputs.begin(); 149 return arg_end(); 150 } 151 const_op_iterator gc_transition_args_end() const { 152 if (auto Opt = getOperandBundle(LLVMContext::OB_gc_transition)) 153 return Opt->Inputs.end(); 154 return arg_end(); 155 } 156 157 /// range adapter for GC transition arguments 158 iterator_range<const_op_iterator> gc_transition_args() const { 159 return make_range(gc_transition_args_begin(), gc_transition_args_end()); 160 } 161 162 const_op_iterator deopt_begin() const { 163 if (auto Opt = getOperandBundle(LLVMContext::OB_deopt)) 164 return Opt->Inputs.begin(); 165 return arg_end(); 166 } 167 const_op_iterator deopt_end() const { 168 if (auto Opt = getOperandBundle(LLVMContext::OB_deopt)) 169 return Opt->Inputs.end(); 170 return arg_end(); 171 } 172 173 /// range adapter for vm state arguments 174 iterator_range<const_op_iterator> deopt_operands() const { 175 return make_range(deopt_begin(), deopt_end()); 176 } 177 178 /// Returns an iterator to the begining of the argument range describing gc 179 /// values for the statepoint. 180 const_op_iterator gc_args_begin() const { 181 if (auto Opt = getOperandBundle(LLVMContext::OB_gc_live)) 182 return Opt->Inputs.begin(); 183 return arg_end(); 184 } 185 186 /// Return an end iterator for the gc argument range 187 const_op_iterator gc_args_end() const { 188 if (auto Opt = getOperandBundle(LLVMContext::OB_gc_live)) 189 return Opt->Inputs.end(); 190 return arg_end(); 191 } 192 193 /// range adapter for gc arguments 194 iterator_range<const_op_iterator> gc_args() const { 195 return make_range(gc_args_begin(), gc_args_end()); 196 } 197 198 199 /// Get list of all gc reloactes linked to this statepoint 200 /// May contain several relocations for the same base/derived pair. 201 /// For example this could happen due to relocations on unwinding 202 /// path of invoke. 203 inline std::vector<const GCRelocateInst *> getGCRelocates() const; 204 }; 205 206 std::vector<const GCRelocateInst *> GCStatepointInst::getGCRelocates() const { 207 std::vector<const GCRelocateInst *> Result; 208 209 // Search for relocated pointers. Note that working backwards from the 210 // gc_relocates ensures that we only get pairs which are actually relocated 211 // and used after the statepoint. 212 for (const User *U : users()) 213 if (auto *Relocate = dyn_cast<GCRelocateInst>(U)) 214 Result.push_back(Relocate); 215 216 auto *StatepointInvoke = dyn_cast<InvokeInst>(this); 217 if (!StatepointInvoke) 218 return Result; 219 220 // We need to scan thorough exceptional relocations if it is invoke statepoint 221 LandingPadInst *LandingPad = StatepointInvoke->getLandingPadInst(); 222 223 // Search for gc relocates that are attached to this landingpad. 224 for (const User *LandingPadUser : LandingPad->users()) { 225 if (auto *Relocate = dyn_cast<GCRelocateInst>(LandingPadUser)) 226 Result.push_back(Relocate); 227 } 228 return Result; 229 } 230 231 /// Call sites that get wrapped by a gc.statepoint (currently only in 232 /// RewriteStatepointsForGC and potentially in other passes in the future) can 233 /// have attributes that describe properties of gc.statepoint call they will be 234 /// eventually be wrapped in. This struct is used represent such directives. 235 struct StatepointDirectives { 236 Optional<uint32_t> NumPatchBytes; 237 Optional<uint64_t> StatepointID; 238 239 static const uint64_t DefaultStatepointID = 0xABCDEF00; 240 static const uint64_t DeoptBundleStatepointID = 0xABCDEF0F; 241 }; 242 243 /// Parse out statepoint directives from the function attributes present in \p 244 /// AS. 245 StatepointDirectives parseStatepointDirectivesFromAttrs(AttributeList AS); 246 247 /// Return \c true if the \p Attr is an attribute that is a statepoint 248 /// directive. 249 bool isStatepointDirectiveAttr(Attribute Attr); 250 251 } // end namespace llvm 252 253 #endif // LLVM_IR_STATEPOINT_H 254