LLVM  4.0.0
CoroInstr.h
Go to the documentation of this file.
1 //===-- CoroInstr.h - Coroutine Intrinsics Instruction Wrappers -*- C++ -*-===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 // This file defines classes that make it really easy to deal with intrinsic
10 // functions with the isa/dyncast family of functions. In particular, this
11 // allows you to do things like:
12 //
13 // if (auto *SF = dyn_cast<CoroSubFnInst>(Inst))
14 // ... SF->getFrame() ...
15 //
16 // All intrinsic function calls are instances of the call instruction, so these
17 // are all subclasses of the CallInst class. Note that none of these classes
18 // has state or virtual methods, which is an important part of this gross/neat
19 // hack working.
20 //
21 // The helpful comment above is borrowed from llvm/IntrinsicInst.h, we keep
22 // coroutine intrinsic wrappers here since they are only used by the passes in
23 // the Coroutine library.
24 //===----------------------------------------------------------------------===//
25 
26 #include "llvm/IR/GlobalVariable.h"
27 #include "llvm/IR/IntrinsicInst.h"
28 
29 namespace llvm {
30 
31 /// This class represents the llvm.coro.subfn.addr instruction.
33  enum { FrameArg, IndexArg };
34 
35 public:
36  enum ResumeKind {
37  RestartTrigger = -1,
42  IndexFirst = RestartTrigger
43  };
44 
45  Value *getFrame() const { return getArgOperand(FrameArg); }
46  ResumeKind getIndex() const {
47  int64_t Index = getRawIndex()->getValue().getSExtValue();
48  assert(Index >= IndexFirst && Index < IndexLast &&
49  "unexpected CoroSubFnInst index argument");
50  return static_cast<ResumeKind>(Index);
51  }
52 
54  return cast<ConstantInt>(getArgOperand(IndexArg));
55  }
56 
57  // Methods to support type inquiry through isa, cast, and dyn_cast:
58  static inline bool classof(const IntrinsicInst *I) {
59  return I->getIntrinsicID() == Intrinsic::coro_subfn_addr;
60  }
61  static inline bool classof(const Value *V) {
62  return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
63  }
64 };
65 
66 /// This represents the llvm.coro.alloc instruction.
68 public:
69  // Methods to support type inquiry through isa, cast, and dyn_cast:
70  static inline bool classof(const IntrinsicInst *I) {
71  return I->getIntrinsicID() == Intrinsic::coro_alloc;
72  }
73  static inline bool classof(const Value *V) {
74  return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
75  }
76 };
77 
78 /// This represents the llvm.coro.alloc instruction.
80  enum { AlignArg, PromiseArg, CoroutineArg, InfoArg };
81 
82 public:
84  for (User *U : users())
85  if (auto *CA = dyn_cast<CoroAllocInst>(U))
86  return CA;
87  return nullptr;
88  }
89 
91  for (User *U : users())
92  if (auto *II = dyn_cast<IntrinsicInst>(U))
93  if (II->getIntrinsicID() == Intrinsic::coro_begin)
94  return II;
95  llvm_unreachable("no coro.begin associated with coro.id");
96  }
97 
99  Value *Arg = getArgOperand(PromiseArg);
100  return isa<ConstantPointerNull>(Arg)
101  ? nullptr
102  : cast<AllocaInst>(Arg->stripPointerCasts());
103  }
104 
105  void clearPromise() {
106  Value *Arg = getArgOperand(PromiseArg);
107  setArgOperand(PromiseArg,
109  if (isa<AllocaInst>(Arg))
110  return;
111  assert((isa<BitCastInst>(Arg) || isa<GetElementPtrInst>(Arg)) &&
112  "unexpected instruction designating the promise");
113  // TODO: Add a check that any remaining users of Inst are after coro.begin
114  // or add code to move the users after coro.begin.
115  auto *Inst = cast<Instruction>(Arg);
116  if (Inst->use_empty()) {
117  Inst->eraseFromParent();
118  return;
119  }
120  Inst->moveBefore(getCoroBegin()->getNextNode());
121  }
122 
123  // Info argument of coro.id is
124  // fresh out of the frontend: null ;
125  // outlined : {Init, Return, Susp1, Susp2, ...} ;
126  // postsplit : [resume, destroy, cleanup] ;
127  //
128  // If parts of the coroutine were outlined to protect against undesirable
129  // code motion, these functions will be stored in a struct literal referred to
130  // by the Info parameter. Note: this is only needed before coroutine is split.
131  //
132  // After coroutine is split, resume functions are stored in an array
133  // referred to by this parameter.
134 
135  struct Info {
136  ConstantStruct *OutlinedParts = nullptr;
137  ConstantArray *Resumers = nullptr;
138 
139  bool hasOutlinedParts() const { return OutlinedParts != nullptr; }
140  bool isPostSplit() const { return Resumers != nullptr; }
141  bool isPreSplit() const { return !isPostSplit(); }
142  };
143  Info getInfo() const {
144  Info Result;
145  auto *GV = dyn_cast<GlobalVariable>(getRawInfo());
146  if (!GV)
147  return Result;
148 
149  assert(GV->isConstant() && GV->hasDefinitiveInitializer());
150  Constant *Initializer = GV->getInitializer();
151  if ((Result.OutlinedParts = dyn_cast<ConstantStruct>(Initializer)))
152  return Result;
153 
154  Result.Resumers = cast<ConstantArray>(Initializer);
155  return Result;
156  }
157  Constant *getRawInfo() const {
158  return cast<Constant>(getArgOperand(InfoArg)->stripPointerCasts());
159  }
160 
161  void setInfo(Constant *C) { setArgOperand(InfoArg, C); }
162 
164  return cast<Function>(getArgOperand(CoroutineArg)->stripPointerCasts());
165  }
167  assert(isa<ConstantPointerNull>(getArgOperand(CoroutineArg)) &&
168  "Coroutine argument is already assigned");
169  auto *const Int8PtrTy = Type::getInt8PtrTy(getContext());
170  setArgOperand(CoroutineArg,
171  ConstantExpr::getBitCast(getFunction(), Int8PtrTy));
172  }
173 
174  // Methods to support type inquiry through isa, cast, and dyn_cast:
175  static inline bool classof(const IntrinsicInst *I) {
176  return I->getIntrinsicID() == Intrinsic::coro_id;
177  }
178  static inline bool classof(const Value *V) {
179  return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
180  }
181 };
182 
183 /// This represents the llvm.coro.frame instruction.
185 public:
186  // Methods to support type inquiry through isa, cast, and dyn_cast:
187  static inline bool classof(const IntrinsicInst *I) {
188  return I->getIntrinsicID() == Intrinsic::coro_frame;
189  }
190  static inline bool classof(const Value *V) {
191  return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
192  }
193 };
194 
195 /// This represents the llvm.coro.free instruction.
197  enum { IdArg, FrameArg };
198 
199 public:
200  Value *getFrame() const { return getArgOperand(FrameArg); }
201 
202  // Methods to support type inquiry through isa, cast, and dyn_cast:
203  static inline bool classof(const IntrinsicInst *I) {
204  return I->getIntrinsicID() == Intrinsic::coro_free;
205  }
206  static inline bool classof(const Value *V) {
207  return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
208  }
209 };
210 
211 /// This class represents the llvm.coro.begin instruction.
213  enum { IdArg, MemArg };
214 
215 public:
216  CoroIdInst *getId() const { return cast<CoroIdInst>(getArgOperand(IdArg)); }
217 
218  Value *getMem() const { return getArgOperand(MemArg); }
219 
220  // Methods for support type inquiry through isa, cast, and dyn_cast:
221  static inline bool classof(const IntrinsicInst *I) {
222  return I->getIntrinsicID() == Intrinsic::coro_begin;
223  }
224  static inline bool classof(const Value *V) {
225  return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
226  }
227 };
228 
229 /// This represents the llvm.coro.save instruction.
231 public:
232  // Methods to support type inquiry through isa, cast, and dyn_cast:
233  static inline bool classof(const IntrinsicInst *I) {
234  return I->getIntrinsicID() == Intrinsic::coro_save;
235  }
236  static inline bool classof(const Value *V) {
237  return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
238  }
239 };
240 
241 /// This represents the llvm.coro.promise instruction.
243  enum { FrameArg, AlignArg, FromArg };
244 
245 public:
246  bool isFromPromise() const {
247  return cast<Constant>(getArgOperand(FromArg))->isOneValue();
248  }
249  unsigned getAlignment() const {
250  return cast<ConstantInt>(getArgOperand(AlignArg))->getZExtValue();
251  }
252 
253  // Methods to support type inquiry through isa, cast, and dyn_cast:
254  static inline bool classof(const IntrinsicInst *I) {
255  return I->getIntrinsicID() == Intrinsic::coro_promise;
256  }
257  static inline bool classof(const Value *V) {
258  return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
259  }
260 };
261 
262 /// This represents the llvm.coro.suspend instruction.
264  enum { SaveArg, FinalArg };
265 
266 public:
268  Value *Arg = getArgOperand(SaveArg);
269  if (auto *SI = dyn_cast<CoroSaveInst>(Arg))
270  return SI;
271  assert(isa<ConstantTokenNone>(Arg));
272  return nullptr;
273  }
274  bool isFinal() const {
275  return cast<Constant>(getArgOperand(FinalArg))->isOneValue();
276  }
277 
278  // Methods to support type inquiry through isa, cast, and dyn_cast:
279  static inline bool classof(const IntrinsicInst *I) {
280  return I->getIntrinsicID() == Intrinsic::coro_suspend;
281  }
282  static inline bool classof(const Value *V) {
283  return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
284  }
285 };
286 
287 /// This represents the llvm.coro.size instruction.
289 public:
290  // Methods to support type inquiry through isa, cast, and dyn_cast:
291  static inline bool classof(const IntrinsicInst *I) {
292  return I->getIntrinsicID() == Intrinsic::coro_size;
293  }
294  static inline bool classof(const Value *V) {
295  return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
296  }
297 };
298 
299 /// This represents the llvm.coro.end instruction.
301  enum { FrameArg, UnwindArg };
302 
303 public:
304  bool isFallthrough() const { return !isUnwind(); }
305  bool isUnwind() const {
306  return cast<Constant>(getArgOperand(UnwindArg))->isOneValue();
307  }
308 
309  // Methods to support type inquiry through isa, cast, and dyn_cast:
310  static inline bool classof(const IntrinsicInst *I) {
311  return I->getIntrinsicID() == Intrinsic::coro_end;
312  }
313  static inline bool classof(const Value *V) {
314  return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
315  }
316 };
317 
318 } // End namespace llvm.
This represents the llvm.coro.promise instruction.
Definition: CoroInstr.h:242
This represents the llvm.coro.alloc instruction.
Definition: CoroInstr.h:79
Intrinsic::ID getIntrinsicID() const
Return the intrinsic ID of this intrinsic.
Definition: IntrinsicInst.h:51
Value * getFrame() const
Definition: CoroInstr.h:200
static bool classof(const IntrinsicInst *I)
Definition: CoroInstr.h:221
ConstantInt * getRawIndex() const
Definition: CoroInstr.h:53
IntrinsicInst * getCoroBegin()
Definition: CoroInstr.h:90
bool isPreSplit() const
Definition: CoroInstr.h:141
static bool classof(const IntrinsicInst *I)
Definition: CoroInstr.h:175
unsigned getAlignment() const
Definition: CoroInstr.h:249
static bool classof(const IntrinsicInst *I)
Definition: CoroInstr.h:310
static bool classof(const Value *V)
Definition: CoroInstr.h:224
ResumeKind getIndex() const
Definition: CoroInstr.h:46
This represents the llvm.coro.suspend instruction.
Definition: CoroInstr.h:263
static bool classof(const IntrinsicInst *I)
Definition: CoroInstr.h:187
CoroIdInst * getId() const
Definition: CoroInstr.h:216
This class represents the llvm.coro.subfn.addr instruction.
Definition: CoroInstr.h:32
ConstantStruct * OutlinedParts
Definition: CoroInstr.h:136
static bool classof(const IntrinsicInst *I)
Definition: CoroInstr.h:233
This represents the llvm.coro.alloc instruction.
Definition: CoroInstr.h:67
static bool classof(const IntrinsicInst *I)
Definition: CoroInstr.h:58
void setCoroutineSelf()
Definition: CoroInstr.h:166
static bool classof(const Value *V)
Definition: CoroInstr.h:236
CoroSaveInst * getCoroSave() const
Definition: CoroInstr.h:267
Constant * getRawInfo() const
Definition: CoroInstr.h:157
static Constant * getBitCast(Constant *C, Type *Ty, bool OnlyIfReduced=false)
Definition: Constants.cpp:1695
This represents the llvm.coro.size instruction.
Definition: CoroInstr.h:288
static ConstantPointerNull * get(PointerType *T)
Static factory methods - Return objects of the specified value.
Definition: Constants.cpp:1323
This is an important base class in LLVM.
Definition: Constant.h:42
Function * getCoroutine() const
Definition: CoroInstr.h:163
static bool classof(const Value *V)
Definition: CoroInstr.h:61
This represents the llvm.coro.end instruction.
Definition: CoroInstr.h:300
Value * getMem() const
Definition: CoroInstr.h:218
This represents the llvm.coro.save instruction.
Definition: CoroInstr.h:230
#define LLVM_LIBRARY_VISIBILITY
LLVM_LIBRARY_VISIBILITY - If a class marked with this attribute is linked into a shared library...
Definition: Compiler.h:105
static bool classof(const Value *V)
Definition: CoroInstr.h:294
Info getInfo() const
Definition: CoroInstr.h:143
static bool classof(const Value *V)
Definition: CoroInstr.h:190
static PointerType * getInt8PtrTy(LLVMContext &C, unsigned AS=0)
Definition: Type.cpp:213
This represents the llvm.coro.free instruction.
Definition: CoroInstr.h:196
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
static bool classof(const IntrinsicInst *I)
Definition: CoroInstr.h:254
static bool classof(const Value *V)
Definition: CoroInstr.h:282
This is the shared class of boolean and integer constants.
Definition: Constants.h:88
bool isFinal() const
Definition: CoroInstr.h:274
Value * stripPointerCasts()
Strip off pointer casts, all-zero GEPs, and aliases.
Definition: Value.cpp:490
static bool classof(const Value *V)
Definition: CoroInstr.h:73
bool isFromPromise() const
Definition: CoroInstr.h:246
static GCRegistry::Add< ShadowStackGC > C("shadow-stack","Very portable GC for uncooperative code generators")
bool hasOutlinedParts() const
Definition: CoroInstr.h:139
This class represents the llvm.coro.begin instruction.
Definition: CoroInstr.h:212
ConstantArray - Constant Array Declarations.
Definition: Constants.h:411
ConstantArray * Resumers
Definition: CoroInstr.h:137
static bool classof(const IntrinsicInst *I)
Definition: CoroInstr.h:203
void clearPromise()
Definition: CoroInstr.h:105
iv users
Definition: IVUsers.cpp:51
static bool classof(const Value *V)
Definition: CoroInstr.h:313
static bool classof(const Value *V)
Definition: CoroInstr.h:206
static bool classof(const IntrinsicInst *I)
Definition: CoroInstr.h:291
static bool classof(const IntrinsicInst *I)
Definition: CoroInstr.h:279
Value * getFrame() const
Definition: CoroInstr.h:45
static bool classof(const Value *V)
Definition: CoroInstr.h:178
#define I(x, y, z)
Definition: MD5.cpp:54
static bool classof(const IntrinsicInst *I)
Definition: CoroInstr.h:70
LLVM_NODISCARD std::enable_if<!is_simple_type< Y >::value, typename cast_retty< X, const Y >::ret_type >::type dyn_cast(const Y &Val)
Definition: Casting.h:287
bool isPostSplit() const
Definition: CoroInstr.h:140
bool isFallthrough() const
Definition: CoroInstr.h:304
bool isUnwind() const
Definition: CoroInstr.h:305
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
This represents the llvm.coro.frame instruction.
Definition: CoroInstr.h:184
LLVM Value Representation.
Definition: Value.h:71
void setInfo(Constant *C)
Definition: CoroInstr.h:161
AllocaInst * getPromise() const
Definition: CoroInstr.h:98
CoroAllocInst * getCoroAlloc()
Definition: CoroInstr.h:83
static bool classof(const Value *V)
Definition: CoroInstr.h:257
A wrapper class for inspecting calls to intrinsic functions.
Definition: IntrinsicInst.h:44
an instruction to allocate memory on the stack
Definition: Instructions.h:60