Statepoint.h 12 KB

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