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