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 class GCRelocateInst; 56 class GCResultInst; 57 58 bool isStatepoint(const CallBase *Call); 59 bool isStatepoint(const Value *V); 60 bool isStatepoint(const Value &V); 61 62 bool isGCRelocate(const CallBase *Call); 63 bool isGCRelocate(const Value *V); 64 65 bool isGCResult(const CallBase *Call); 66 bool isGCResult(const Value *V); 67 68 /// A wrapper around a GC intrinsic call, this provides most of the actual 69 /// functionality for Statepoint and ImmutableStatepoint. It is 70 /// templatized to allow easily specializing of const and non-const 71 /// concrete subtypes. 72 template <typename FunTy, typename InstructionTy, typename ValueTy, 73 typename CallBaseTy> 74 class StatepointBase { 75 CallBaseTy *StatepointCall; 76 77 protected: 78 explicit StatepointBase(InstructionTy *I) { 79 StatepointCall = isStatepoint(I) ? cast<CallBaseTy>(I) : nullptr; 80 } 81 82 explicit StatepointBase(CallBaseTy *Call) { 83 StatepointCall = isStatepoint(Call) ? Call : nullptr; 84 } 85 86 public: 87 using arg_iterator = typename CallBaseTy::const_op_iterator; 88 89 enum { 90 IDPos = 0, 91 NumPatchBytesPos = 1, 92 CalledFunctionPos = 2, 93 NumCallArgsPos = 3, 94 FlagsPos = 4, 95 CallArgsBeginPos = 5, 96 }; 97 98 void *operator new(size_t, unsigned) = delete; 99 void *operator new(size_t s) = delete; 100 101 explicit operator bool() const { 102 // We do not assign non-statepoint call instructions to StatepointCall. 103 return (bool)StatepointCall; 104 } 105 106 /// Return the underlying call instruction. 107 CallBaseTy *getCall() const { 108 assert(*this && "check validity first!"); 109 return StatepointCall; 110 } 111 112 uint64_t getFlags() const { 113 return cast<ConstantInt>(getCall()->getArgOperand(FlagsPos)) 114 ->getZExtValue(); 115 } 116 117 /// Return the ID associated with this statepoint. 118 uint64_t getID() const { 119 const Value *IDVal = getCall()->getArgOperand(IDPos); 120 return cast<ConstantInt>(IDVal)->getZExtValue(); 121 } 122 123 /// Return the number of patchable bytes associated with this statepoint. 124 uint32_t getNumPatchBytes() const { 125 const Value *NumPatchBytesVal = getCall()->getArgOperand(NumPatchBytesPos); 126 uint64_t NumPatchBytes = 127 cast<ConstantInt>(NumPatchBytesVal)->getZExtValue(); 128 assert(isInt<32>(NumPatchBytes) && "should fit in 32 bits!"); 129 return NumPatchBytes; 130 } 131 132 /// Return the value actually being called or invoked. 133 ValueTy *getCalledValue() const { 134 return getCall()->getArgOperand(CalledFunctionPos); 135 } 136 137 // FIXME: Migrate users of this to `getCall` and remove it. 138 InstructionTy *getInstruction() const { return getCall(); } 139 140 /// Return the function being called if this is a direct call, otherwise 141 /// return null (if it's an indirect call). 142 FunTy *getCalledFunction() const { 143 return dyn_cast<Function>(getCalledValue()); 144 } 145 146 /// Return the caller function for this statepoint. 147 FunTy *getCaller() const { return getCall()->getCaller(); } 148 149 /// Determine if the statepoint cannot unwind. 150 bool doesNotThrow() const { 151 Function *F = getCalledFunction(); 152 return getCall()->doesNotThrow() || (F ? F->doesNotThrow() : false); 153 } 154 155 /// Return the type of the value returned by the call underlying the 156 /// statepoint. 157 Type *getActualReturnType() const { 158 auto *FTy = cast<FunctionType>( 159 cast<PointerType>(getCalledValue()->getType())->getElementType()); 160 return FTy->getReturnType(); 161 } 162 163 /// Number of arguments to be passed to the actual callee. 164 int getNumCallArgs() const { 165 const Value *NumCallArgsVal = getCall()->getArgOperand(NumCallArgsPos); 166 return cast<ConstantInt>(NumCallArgsVal)->getZExtValue(); 167 } 168 169 size_t arg_size() const { return getNumCallArgs(); } 170 arg_iterator arg_begin() const { 171 assert(CallArgsBeginPos <= (int)getCall()->arg_size()); 172 return getCall()->arg_begin() + CallArgsBeginPos; 173 } 174 arg_iterator arg_end() const { 175 auto I = arg_begin() + arg_size(); 176 assert((getCall()->arg_end() - I) >= 0); 177 return I; 178 } 179 180 ValueTy *getArgument(unsigned Index) { 181 assert(Index < arg_size() && "out of bounds!"); 182 return *(arg_begin() + Index); 183 } 184 185 /// range adapter for call arguments 186 iterator_range<arg_iterator> call_args() const { 187 return make_range(arg_begin(), arg_end()); 188 } 189 190 /// Return true if the call or the callee has the given attribute. 191 bool paramHasAttr(unsigned i, Attribute::AttrKind A) const { 192 Function *F = getCalledFunction(); 193 return getCall()->paramHasAttr(i + CallArgsBeginPos, A) || 194 (F ? F->getAttributes().hasAttribute(i, A) : false); 195 } 196 197 /// Number of GC transition args. 198 int getNumTotalGCTransitionArgs() const { 199 const Value *NumGCTransitionArgs = *arg_end(); 200 return cast<ConstantInt>(NumGCTransitionArgs)->getZExtValue(); 201 } 202 arg_iterator gc_transition_args_begin() const { 203 auto I = arg_end() + 1; 204 assert((getCall()->arg_end() - I) >= 0); 205 return I; 206 } 207 arg_iterator gc_transition_args_end() const { 208 auto I = gc_transition_args_begin() + getNumTotalGCTransitionArgs(); 209 assert((getCall()->arg_end() - I) >= 0); 210 return I; 211 } 212 213 /// range adapter for GC transition arguments 214 iterator_range<arg_iterator> gc_transition_args() const { 215 return make_range(gc_transition_args_begin(), gc_transition_args_end()); 216 } 217 218 /// Number of additional arguments excluding those intended 219 /// for garbage collection. 220 int getNumTotalVMSArgs() const { 221 const Value *NumVMSArgs = *gc_transition_args_end(); 222 return cast<ConstantInt>(NumVMSArgs)->getZExtValue(); 223 } 224 225 arg_iterator deopt_begin() const { 226 auto I = gc_transition_args_end() + 1; 227 assert((getCall()->arg_end() - I) >= 0); 228 return I; 229 } 230 arg_iterator deopt_end() const { 231 auto I = deopt_begin() + getNumTotalVMSArgs(); 232 assert((getCall()->arg_end() - I) >= 0); 233 return I; 234 } 235 236 /// range adapter for vm state arguments 237 iterator_range<arg_iterator> deopt_operands() const { 238 return make_range(deopt_begin(), deopt_end()); 239 } 240 241 arg_iterator gc_args_begin() const { return deopt_end(); } 242 arg_iterator gc_args_end() const { return getCall()->arg_end(); } 243 244 unsigned gcArgsStartIdx() const { 245 return gc_args_begin() - getCall()->op_begin(); 246 } 247 248 /// range adapter for gc arguments 249 iterator_range<arg_iterator> gc_args() const { 250 return make_range(gc_args_begin(), gc_args_end()); 251 } 252 253 /// Get list of all gc reloactes linked to this statepoint 254 /// May contain several relocations for the same base/derived pair. 255 /// For example this could happen due to relocations on unwinding 256 /// path of invoke. 257 std::vector<const GCRelocateInst *> getRelocates() const; 258 259 /// Get the experimental_gc_result call tied to this statepoint. Can be 260 /// nullptr if there isn't a gc_result tied to this statepoint. Guaranteed to 261 /// be a CallInst if non-null. 262 const GCResultInst *getGCResult() const { 263 for (auto *U : getInstruction()->users()) 264 if (auto *GRI = dyn_cast<GCResultInst>(U)) 265 return GRI; 266 return nullptr; 267 } 268 269 #ifndef NDEBUG 270 /// Asserts if this statepoint is malformed. Common cases for failure 271 /// include incorrect length prefixes for variable length sections or 272 /// illegal values for parameters. 273 void verify() { 274 assert(getNumCallArgs() >= 0 && 275 "number of arguments to actually callee can't be negative"); 276 277 // The internal asserts in the iterator accessors do the rest. 278 (void)arg_begin(); 279 (void)arg_end(); 280 (void)gc_transition_args_begin(); 281 (void)gc_transition_args_end(); 282 (void)deopt_begin(); 283 (void)deopt_end(); 284 (void)gc_args_begin(); 285 (void)gc_args_end(); 286 } 287 #endif 288 }; 289 290 /// A specialization of it's base class for read only access 291 /// to a gc.statepoint. 292 class ImmutableStatepoint 293 : public StatepointBase<const Function, const Instruction, const Value, 294 const CallBase> { 295 using Base = StatepointBase<const Function, const Instruction, const Value, 296 const CallBase>; 297 298 public: 299 explicit ImmutableStatepoint(const Instruction *I) : Base(I) {} 300 explicit ImmutableStatepoint(const CallBase *Call) : Base(Call) {} 301 }; 302 303 /// A specialization of it's base class for read-write access 304 /// to a gc.statepoint. 305 class Statepoint 306 : public StatepointBase<Function, Instruction, Value, CallBase> { 307 using Base = StatepointBase<Function, Instruction, Value, CallBase>; 308 309 public: 310 explicit Statepoint(Instruction *I) : Base(I) {} 311 explicit Statepoint(CallBase *Call) : Base(Call) {} 312 }; 313 314 /// Common base class for representing values projected from a statepoint. 315 /// Currently, the only projections available are gc.result and gc.relocate. 316 class GCProjectionInst : public IntrinsicInst { 317 public: 318 static bool classof(const IntrinsicInst *I) { 319 return I->getIntrinsicID() == Intrinsic::experimental_gc_relocate || 320 I->getIntrinsicID() == Intrinsic::experimental_gc_result; 321 } 322 323 static bool classof(const Value *V) { 324 return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V)); 325 } 326 327 /// Return true if this relocate is tied to the invoke statepoint. 328 /// This includes relocates which are on the unwinding path. 329 bool isTiedToInvoke() const { 330 const Value *Token = getArgOperand(0); 331 332 return isa<LandingPadInst>(Token) || isa<InvokeInst>(Token); 333 } 334 335 /// The statepoint with which this gc.relocate is associated. 336 const CallBase *getStatepoint() const { 337 const Value *Token = getArgOperand(0); 338 339 // This takes care both of relocates for call statepoints and relocates 340 // on normal path of invoke statepoint. 341 if (!isa<LandingPadInst>(Token)) { 342 assert(isStatepoint(Token)); 343 return cast<CallBase>(Token); 344 } 345 346 // This relocate is on exceptional path of an invoke statepoint 347 const BasicBlock *InvokeBB = 348 cast<Instruction>(Token)->getParent()->getUniquePredecessor(); 349 350 assert(InvokeBB && "safepoints should have unique landingpads"); 351 assert(InvokeBB->getTerminator() && 352 "safepoint block should be well formed"); 353 assert(isStatepoint(InvokeBB->getTerminator())); 354 355 return cast<CallBase>(InvokeBB->getTerminator()); 356 } 357 }; 358 359 /// Represents calls to the gc.relocate intrinsic. 360 class GCRelocateInst : public GCProjectionInst { 361 public: 362 static bool classof(const IntrinsicInst *I) { 363 return I->getIntrinsicID() == Intrinsic::experimental_gc_relocate; 364 } 365 366 static bool classof(const Value *V) { 367 return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V)); 368 } 369 370 /// The index into the associate statepoint's argument list 371 /// which contains the base pointer of the pointer whose 372 /// relocation this gc.relocate describes. 373 unsigned getBasePtrIndex() const { 374 return cast<ConstantInt>(getArgOperand(1))->getZExtValue(); 375 } 376 377 /// The index into the associate statepoint's argument list which 378 /// contains the pointer whose relocation this gc.relocate describes. 379 unsigned getDerivedPtrIndex() const { 380 return cast<ConstantInt>(getArgOperand(2))->getZExtValue(); 381 } 382 383 Value *getBasePtr() const { 384 return *(getStatepoint()->arg_begin() + getBasePtrIndex()); 385 } 386 387 Value *getDerivedPtr() const { 388 return *(getStatepoint()->arg_begin() + getDerivedPtrIndex()); 389 } 390 }; 391 392 /// Represents calls to the gc.result intrinsic. 393 class GCResultInst : public GCProjectionInst { 394 public: 395 static bool classof(const IntrinsicInst *I) { 396 return I->getIntrinsicID() == Intrinsic::experimental_gc_result; 397 } 398 399 static bool classof(const Value *V) { 400 return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V)); 401 } 402 }; 403 404 template <typename FunTy, typename InstructionTy, typename ValueTy, 405 typename CallBaseTy> 406 std::vector<const GCRelocateInst *> 407 StatepointBase<FunTy, InstructionTy, ValueTy, CallBaseTy>::getRelocates() 408 const { 409 std::vector<const GCRelocateInst *> Result; 410 411 // Search for relocated pointers. Note that working backwards from the 412 // gc_relocates ensures that we only get pairs which are actually relocated 413 // and used after the statepoint. 414 for (const User *U : StatepointCall->users()) 415 if (auto *Relocate = dyn_cast<GCRelocateInst>(U)) 416 Result.push_back(Relocate); 417 418 auto *StatepointInvoke = dyn_cast<InvokeInst>(StatepointCall); 419 if (!StatepointInvoke) 420 return Result; 421 422 // We need to scan thorough exceptional relocations if it is invoke statepoint 423 LandingPadInst *LandingPad = StatepointInvoke->getLandingPadInst(); 424 425 // Search for gc relocates that are attached to this landingpad. 426 for (const User *LandingPadUser : LandingPad->users()) { 427 if (auto *Relocate = dyn_cast<GCRelocateInst>(LandingPadUser)) 428 Result.push_back(Relocate); 429 } 430 return Result; 431 } 432 433 /// Call sites that get wrapped by a gc.statepoint (currently only in 434 /// RewriteStatepointsForGC and potentially in other passes in the future) can 435 /// have attributes that describe properties of gc.statepoint call they will be 436 /// eventually be wrapped in. This struct is used represent such directives. 437 struct StatepointDirectives { 438 Optional<uint32_t> NumPatchBytes; 439 Optional<uint64_t> StatepointID; 440 441 static const uint64_t DefaultStatepointID = 0xABCDEF00; 442 static const uint64_t DeoptBundleStatepointID = 0xABCDEF0F; 443 }; 444 445 /// Parse out statepoint directives from the function attributes present in \p 446 /// AS. 447 StatepointDirectives parseStatepointDirectivesFromAttrs(AttributeList AS); 448 449 /// Return \c true if the \p Attr is an attribute that is a statepoint 450 /// directive. 451 bool isStatepointDirectiveAttr(Attribute Attr); 452 453 } // end namespace llvm 454 455 #endif // LLVM_IR_STATEPOINT_H 456