File indexing completed on 2026-05-10 08:44:10
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016 #ifndef LLVM_IR_STATEPOINT_H
0017 #define LLVM_IR_STATEPOINT_H
0018
0019 #include "llvm/ADT/iterator_range.h"
0020 #include "llvm/IR/Attributes.h"
0021 #include "llvm/IR/Constants.h"
0022 #include "llvm/IR/Function.h"
0023 #include "llvm/IR/InstrTypes.h"
0024 #include "llvm/IR/Instructions.h"
0025 #include "llvm/IR/IntrinsicInst.h"
0026 #include "llvm/IR/Intrinsics.h"
0027 #include "llvm/Support/Casting.h"
0028 #include "llvm/Support/MathExtras.h"
0029 #include <cassert>
0030 #include <cstddef>
0031 #include <cstdint>
0032 #include <optional>
0033 #include <vector>
0034
0035 namespace llvm {
0036
0037
0038
0039 enum class StatepointFlags {
0040 None = 0,
0041 GCTransition = 1,
0042
0043
0044
0045
0046
0047
0048
0049 DeoptLiveIn = 2,
0050
0051 MaskAll = 3
0052 };
0053
0054
0055
0056 class GCRelocateInst;
0057
0058
0059
0060
0061 class GCStatepointInst : public CallBase {
0062 public:
0063 GCStatepointInst() = delete;
0064 GCStatepointInst(const GCStatepointInst &) = delete;
0065 GCStatepointInst &operator=(const GCStatepointInst &) = delete;
0066
0067 static bool classof(const CallBase *I) {
0068 if (const Function *CF = I->getCalledFunction())
0069 return CF->getIntrinsicID() == Intrinsic::experimental_gc_statepoint;
0070 return false;
0071 }
0072
0073 static bool classof(const Value *V) {
0074 return isa<CallBase>(V) && classof(cast<CallBase>(V));
0075 }
0076
0077 enum {
0078 IDPos = 0,
0079 NumPatchBytesPos = 1,
0080 CalledFunctionPos = 2,
0081 NumCallArgsPos = 3,
0082 FlagsPos = 4,
0083 CallArgsBeginPos = 5,
0084 };
0085
0086
0087 uint64_t getID() const {
0088 return cast<ConstantInt>(getArgOperand(IDPos))->getZExtValue();
0089 }
0090
0091
0092 uint32_t getNumPatchBytes() const {
0093 const Value *NumPatchBytesVal = getArgOperand(NumPatchBytesPos);
0094 uint64_t NumPatchBytes =
0095 cast<ConstantInt>(NumPatchBytesVal)->getZExtValue();
0096 assert(isInt<32>(NumPatchBytes) && "should fit in 32 bits!");
0097 return NumPatchBytes;
0098 }
0099
0100
0101 int getNumCallArgs() const {
0102 return cast<ConstantInt>(getArgOperand(NumCallArgsPos))->getZExtValue();
0103 }
0104
0105 uint64_t getFlags() const {
0106 return cast<ConstantInt>(getArgOperand(FlagsPos))->getZExtValue();
0107 }
0108
0109
0110 Value *getActualCalledOperand() const {
0111 return getArgOperand(CalledFunctionPos);
0112 }
0113
0114
0115
0116 Function *getActualCalledFunction() const {
0117 return dyn_cast_or_null<Function>(getActualCalledOperand());
0118 }
0119
0120
0121
0122 Type *getActualReturnType() const {
0123 auto *FT = cast<FunctionType>(getParamElementType(CalledFunctionPos));
0124 return FT->getReturnType();
0125 }
0126
0127
0128
0129 size_t actual_arg_size() const { return getNumCallArgs(); }
0130
0131 const_op_iterator actual_arg_begin() const {
0132 assert(CallArgsBeginPos <= (int)arg_size());
0133 return arg_begin() + CallArgsBeginPos;
0134 }
0135
0136 const_op_iterator actual_arg_end() const {
0137 auto I = actual_arg_begin() + actual_arg_size();
0138 assert((arg_end() - I) == 2);
0139 return I;
0140 }
0141
0142 iterator_range<const_op_iterator> actual_args() const {
0143 return make_range(actual_arg_begin(), actual_arg_end());
0144 }
0145
0146 const_op_iterator gc_transition_args_begin() const {
0147 if (auto Opt = getOperandBundle(LLVMContext::OB_gc_transition))
0148 return Opt->Inputs.begin();
0149 return arg_end();
0150 }
0151 const_op_iterator gc_transition_args_end() const {
0152 if (auto Opt = getOperandBundle(LLVMContext::OB_gc_transition))
0153 return Opt->Inputs.end();
0154 return arg_end();
0155 }
0156
0157
0158 iterator_range<const_op_iterator> gc_transition_args() const {
0159 return make_range(gc_transition_args_begin(), gc_transition_args_end());
0160 }
0161
0162 const_op_iterator deopt_begin() const {
0163 if (auto Opt = getOperandBundle(LLVMContext::OB_deopt))
0164 return Opt->Inputs.begin();
0165 return arg_end();
0166 }
0167 const_op_iterator deopt_end() const {
0168 if (auto Opt = getOperandBundle(LLVMContext::OB_deopt))
0169 return Opt->Inputs.end();
0170 return arg_end();
0171 }
0172
0173
0174 iterator_range<const_op_iterator> deopt_operands() const {
0175 return make_range(deopt_begin(), deopt_end());
0176 }
0177
0178
0179
0180 const_op_iterator gc_live_begin() const {
0181 if (auto Opt = getOperandBundle(LLVMContext::OB_gc_live))
0182 return Opt->Inputs.begin();
0183 return arg_end();
0184 }
0185
0186
0187 const_op_iterator gc_live_end() const {
0188 if (auto Opt = getOperandBundle(LLVMContext::OB_gc_live))
0189 return Opt->Inputs.end();
0190 return arg_end();
0191 }
0192
0193
0194 iterator_range<const_op_iterator> gc_live() const {
0195 return make_range(gc_live_begin(), gc_live_end());
0196 }
0197
0198
0199
0200
0201
0202
0203 inline std::vector<const GCRelocateInst *> getGCRelocates() const;
0204 };
0205
0206 std::vector<const GCRelocateInst *> GCStatepointInst::getGCRelocates() const {
0207 std::vector<const GCRelocateInst *> Result;
0208
0209
0210
0211
0212 for (const User *U : users())
0213 if (auto *Relocate = dyn_cast<GCRelocateInst>(U))
0214 Result.push_back(Relocate);
0215
0216 auto *StatepointInvoke = dyn_cast<InvokeInst>(this);
0217 if (!StatepointInvoke)
0218 return Result;
0219
0220
0221 LandingPadInst *LandingPad = StatepointInvoke->getLandingPadInst();
0222
0223
0224 for (const User *LandingPadUser : LandingPad->users()) {
0225 if (auto *Relocate = dyn_cast<GCRelocateInst>(LandingPadUser))
0226 Result.push_back(Relocate);
0227 }
0228 return Result;
0229 }
0230
0231
0232
0233
0234
0235 struct StatepointDirectives {
0236 std::optional<uint32_t> NumPatchBytes;
0237 std::optional<uint64_t> StatepointID;
0238
0239 static const uint64_t DefaultStatepointID = 0xABCDEF00;
0240 static const uint64_t DeoptBundleStatepointID = 0xABCDEF0F;
0241 };
0242
0243
0244
0245 StatepointDirectives parseStatepointDirectivesFromAttrs(AttributeList AS);
0246
0247
0248
0249 bool isStatepointDirectiveAttr(Attribute Attr);
0250
0251 }
0252
0253 #endif