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 class GCResultInst; 58 59 /// Represents a gc.statepoint intrinsic call. This extends directly from 60 /// CallBase as the IntrinsicInst only supports calls and gc.statepoint is 61 /// invokable. 62 class GCStatepointInst : public CallBase { 63 public: 64 GCStatepointInst() = delete; 65 GCStatepointInst(const GCStatepointInst &) = delete; 66 GCStatepointInst &operator=(const GCStatepointInst &) = delete; 67 68 static bool classof(const CallBase *I) { 69 if (const Function *CF = I->getCalledFunction()) 70 return CF->getIntrinsicID() == Intrinsic::experimental_gc_statepoint; 71 return false; 72 } 73 74 static bool classof(const Value *V) { 75 return isa<CallBase>(V) && classof(cast<CallBase>(V)); 76 } 77 78 enum { 79 IDPos = 0, 80 NumPatchBytesPos = 1, 81 CalledFunctionPos = 2, 82 NumCallArgsPos = 3, 83 FlagsPos = 4, 84 CallArgsBeginPos = 5, 85 }; 86 87 /// Return the ID associated with this statepoint. 88 uint64_t getID() const { 89 return cast<ConstantInt>(getArgOperand(IDPos))->getZExtValue(); 90 } 91 92 /// Return the number of patchable bytes associated with this statepoint. 93 uint32_t getNumPatchBytes() const { 94 const Value *NumPatchBytesVal = getArgOperand(NumPatchBytesPos); 95 uint64_t NumPatchBytes = 96 cast<ConstantInt>(NumPatchBytesVal)->getZExtValue(); 97 assert(isInt<32>(NumPatchBytes) && "should fit in 32 bits!"); 98 return NumPatchBytes; 99 } 100 101 /// Number of arguments to be passed to the actual callee. 102 int getNumCallArgs() const { 103 return cast<ConstantInt>(getArgOperand(NumCallArgsPos))->getZExtValue(); 104 } 105 106 uint64_t getFlags() const { 107 return cast<ConstantInt>(getArgOperand(FlagsPos))->getZExtValue(); 108 } 109 110 /// Return the value actually being called or invoked. 111 Value *getActualCalledOperand() const { 112 return getArgOperand(CalledFunctionPos); 113 } 114 115 /// Returns the function called if this is a wrapping a direct call, and null 116 /// otherwise. 117 Function *getActualCalledFunction() const { 118 return dyn_cast_or_null<Function>(getActualCalledOperand()); 119 } 120 121 /// Return the type of the value returned by the call underlying the 122 /// statepoint. 123 Type *getActualReturnType() const { 124 auto *CalleeTy = 125 getActualCalledOperand()->getType()->getPointerElementType(); 126 return cast<FunctionType>(CalleeTy)->getReturnType(); 127 } 128 129 130 /// Return the number of arguments to the underlying call. 131 size_t actual_arg_size() const { return getNumCallArgs(); } 132 /// Return an iterator to the begining of the arguments to the underlying call 133 const_op_iterator actual_arg_begin() const { 134 assert(CallArgsBeginPos <= (int)arg_size()); 135 return arg_begin() + CallArgsBeginPos; 136 } 137 /// Return an end iterator of the arguments to the underlying call 138 const_op_iterator actual_arg_end() const { 139 auto I = actual_arg_begin() + actual_arg_size(); 140 assert((arg_end() - I) == 2); 141 return I; 142 } 143 /// range adapter for actual call arguments 144 iterator_range<const_op_iterator> actual_args() const { 145 return make_range(actual_arg_begin(), actual_arg_end()); 146 } 147 148 const_op_iterator gc_transition_args_begin() const { 149 if (auto Opt = getOperandBundle(LLVMContext::OB_gc_transition)) 150 return Opt->Inputs.begin(); 151 return arg_end(); 152 } 153 const_op_iterator gc_transition_args_end() const { 154 if (auto Opt = getOperandBundle(LLVMContext::OB_gc_transition)) 155 return Opt->Inputs.end(); 156 return arg_end(); 157 } 158 159 /// range adapter for GC transition arguments 160 iterator_range<const_op_iterator> gc_transition_args() const { 161 return make_range(gc_transition_args_begin(), gc_transition_args_end()); 162 } 163 164 const_op_iterator deopt_begin() const { 165 if (auto Opt = getOperandBundle(LLVMContext::OB_deopt)) 166 return Opt->Inputs.begin(); 167 return arg_end(); 168 } 169 const_op_iterator deopt_end() const { 170 if (auto Opt = getOperandBundle(LLVMContext::OB_deopt)) 171 return Opt->Inputs.end(); 172 return arg_end(); 173 } 174 175 /// range adapter for vm state arguments 176 iterator_range<const_op_iterator> deopt_operands() const { 177 return make_range(deopt_begin(), deopt_end()); 178 } 179 180 /// Returns an iterator to the begining of the argument range describing gc 181 /// values for the statepoint. 182 const_op_iterator gc_args_begin() const { 183 if (auto Opt = getOperandBundle(LLVMContext::OB_gc_live)) 184 return Opt->Inputs.begin(); 185 return arg_end(); 186 } 187 188 /// Return an end iterator for the gc argument range 189 const_op_iterator gc_args_end() const { 190 if (auto Opt = getOperandBundle(LLVMContext::OB_gc_live)) 191 return Opt->Inputs.end(); 192 return arg_end(); 193 } 194 195 /// range adapter for gc arguments 196 iterator_range<const_op_iterator> gc_args() const { 197 return make_range(gc_args_begin(), gc_args_end()); 198 } 199 200 201 /// Get list of all gc reloactes linked to this statepoint 202 /// May contain several relocations for the same base/derived pair. 203 /// For example this could happen due to relocations on unwinding 204 /// path of invoke. 205 inline std::vector<const GCRelocateInst *> getGCRelocates() const; 206 }; 207 208 std::vector<const GCRelocateInst *> GCStatepointInst::getGCRelocates() const { 209 std::vector<const GCRelocateInst *> Result; 210 211 // Search for relocated pointers. Note that working backwards from the 212 // gc_relocates ensures that we only get pairs which are actually relocated 213 // and used after the statepoint. 214 for (const User *U : users()) 215 if (auto *Relocate = dyn_cast<GCRelocateInst>(U)) 216 Result.push_back(Relocate); 217 218 auto *StatepointInvoke = dyn_cast<InvokeInst>(this); 219 if (!StatepointInvoke) 220 return Result; 221 222 // We need to scan thorough exceptional relocations if it is invoke statepoint 223 LandingPadInst *LandingPad = StatepointInvoke->getLandingPadInst(); 224 225 // Search for gc relocates that are attached to this landingpad. 226 for (const User *LandingPadUser : LandingPad->users()) { 227 if (auto *Relocate = dyn_cast<GCRelocateInst>(LandingPadUser)) 228 Result.push_back(Relocate); 229 } 230 return Result; 231 } 232 233 /// Call sites that get wrapped by a gc.statepoint (currently only in 234 /// RewriteStatepointsForGC and potentially in other passes in the future) can 235 /// have attributes that describe properties of gc.statepoint call they will be 236 /// eventually be wrapped in. This struct is used represent such directives. 237 struct StatepointDirectives { 238 Optional<uint32_t> NumPatchBytes; 239 Optional<uint64_t> StatepointID; 240 241 static const uint64_t DefaultStatepointID = 0xABCDEF00; 242 static const uint64_t DeoptBundleStatepointID = 0xABCDEF0F; 243 }; 244 245 /// Parse out statepoint directives from the function attributes present in \p 246 /// AS. 247 StatepointDirectives parseStatepointDirectivesFromAttrs(AttributeList AS); 248 249 /// Return \c true if the \p Attr is an attribute that is a statepoint 250 /// directive. 251 bool isStatepointDirectiveAttr(Attribute Attr); 252 253 } // end namespace llvm 254 255 #endif // LLVM_IR_STATEPOINT_H 256