1 //===-- CoroInstr.h - Coroutine Intrinsics Instruction Wrappers -*- 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 // This file defines classes that make it really easy to deal with intrinsic
9 // functions with the isa/dyncast family of functions.  In particular, this
10 // allows you to do things like:
11 //
12 //     if (auto *SF = dyn_cast<CoroSubFnInst>(Inst))
13 //        ... SF->getFrame() ...
14 //
15 // All intrinsic function calls are instances of the call instruction, so these
16 // are all subclasses of the CallInst class.  Note that none of these classes
17 // has state or virtual methods, which is an important part of this gross/neat
18 // hack working.
19 //
20 // The helpful comment above is borrowed from llvm/IntrinsicInst.h, we keep
21 // coroutine intrinsic wrappers here since they are only used by the passes in
22 // the Coroutine library.
23 //===----------------------------------------------------------------------===//
24 
25 #ifndef LLVM_LIB_TRANSFORMS_COROUTINES_COROINSTR_H
26 #define LLVM_LIB_TRANSFORMS_COROUTINES_COROINSTR_H
27 
28 #include "llvm/IR/GlobalVariable.h"
29 #include "llvm/IR/IntrinsicInst.h"
30 #include "llvm/Support/raw_ostream.h"
31 
32 namespace llvm {
33 
34 /// This class represents the llvm.coro.subfn.addr instruction.
35 class LLVM_LIBRARY_VISIBILITY CoroSubFnInst : public IntrinsicInst {
36   enum { FrameArg, IndexArg };
37 
38 public:
39   enum ResumeKind {
40     RestartTrigger = -1,
41     ResumeIndex,
42     DestroyIndex,
43     CleanupIndex,
44     IndexLast,
45     IndexFirst = RestartTrigger
46   };
47 
getFrame()48   Value *getFrame() const { return getArgOperand(FrameArg); }
getIndex()49   ResumeKind getIndex() const {
50     int64_t Index = getRawIndex()->getValue().getSExtValue();
51     assert(Index >= IndexFirst && Index < IndexLast &&
52            "unexpected CoroSubFnInst index argument");
53     return static_cast<ResumeKind>(Index);
54   }
55 
getRawIndex()56   ConstantInt *getRawIndex() const {
57     return cast<ConstantInt>(getArgOperand(IndexArg));
58   }
59 
60   // Methods to support type inquiry through isa, cast, and dyn_cast:
classof(const IntrinsicInst * I)61   static bool classof(const IntrinsicInst *I) {
62     return I->getIntrinsicID() == Intrinsic::coro_subfn_addr;
63   }
classof(const Value * V)64   static bool classof(const Value *V) {
65     return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
66   }
67 };
68 
69 /// This represents the llvm.coro.alloc instruction.
70 class LLVM_LIBRARY_VISIBILITY CoroAllocInst : public IntrinsicInst {
71 public:
72   // Methods to support type inquiry through isa, cast, and dyn_cast:
classof(const IntrinsicInst * I)73   static bool classof(const IntrinsicInst *I) {
74     return I->getIntrinsicID() == Intrinsic::coro_alloc;
75   }
classof(const Value * V)76   static bool classof(const Value *V) {
77     return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
78   }
79 };
80 
81 /// This represents a common base class for llvm.coro.id instructions.
82 class LLVM_LIBRARY_VISIBILITY AnyCoroIdInst : public IntrinsicInst {
83 public:
getCoroAlloc()84   CoroAllocInst *getCoroAlloc() {
85     for (User *U : users())
86       if (auto *CA = dyn_cast<CoroAllocInst>(U))
87         return CA;
88     return nullptr;
89   }
90 
getCoroBegin()91   IntrinsicInst *getCoroBegin() {
92     for (User *U : users())
93       if (auto *II = dyn_cast<IntrinsicInst>(U))
94         if (II->getIntrinsicID() == Intrinsic::coro_begin)
95           return II;
96     llvm_unreachable("no coro.begin associated with coro.id");
97   }
98 
99   // Methods to support type inquiry through isa, cast, and dyn_cast:
classof(const IntrinsicInst * I)100   static bool classof(const IntrinsicInst *I) {
101     auto ID = I->getIntrinsicID();
102     return ID == Intrinsic::coro_id || ID == Intrinsic::coro_id_retcon ||
103            ID == Intrinsic::coro_id_retcon_once ||
104            ID == Intrinsic::coro_id_async;
105   }
106 
classof(const Value * V)107   static bool classof(const Value *V) {
108     return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
109   }
110 };
111 
112 /// This represents the llvm.coro.id instruction.
113 class LLVM_LIBRARY_VISIBILITY CoroIdInst : public AnyCoroIdInst {
114   enum { AlignArg, PromiseArg, CoroutineArg, InfoArg };
115 
116 public:
getPromise()117   AllocaInst *getPromise() const {
118     Value *Arg = getArgOperand(PromiseArg);
119     return isa<ConstantPointerNull>(Arg)
120                ? nullptr
121                : cast<AllocaInst>(Arg->stripPointerCasts());
122   }
123 
clearPromise()124   void clearPromise() {
125     Value *Arg = getArgOperand(PromiseArg);
126     setArgOperand(PromiseArg, ConstantPointerNull::get(
127                                   PointerType::getUnqual(getContext())));
128     if (isa<AllocaInst>(Arg))
129       return;
130     assert((isa<BitCastInst>(Arg) || isa<GetElementPtrInst>(Arg)) &&
131            "unexpected instruction designating the promise");
132     // TODO: Add a check that any remaining users of Inst are after coro.begin
133     // or add code to move the users after coro.begin.
134     auto *Inst = cast<Instruction>(Arg);
135     if (Inst->use_empty()) {
136       Inst->eraseFromParent();
137       return;
138     }
139     Inst->moveBefore(getCoroBegin()->getNextNode());
140   }
141 
142   // Info argument of coro.id is
143   //   fresh out of the frontend: null ;
144   //   outlined                 : {Init, Return, Susp1, Susp2, ...} ;
145   //   postsplit                : [resume, destroy, cleanup] ;
146   //
147   // If parts of the coroutine were outlined to protect against undesirable
148   // code motion, these functions will be stored in a struct literal referred to
149   // by the Info parameter. Note: this is only needed before coroutine is split.
150   //
151   // After coroutine is split, resume functions are stored in an array
152   // referred to by this parameter.
153 
154   struct Info {
155     ConstantStruct *OutlinedParts = nullptr;
156     ConstantArray *Resumers = nullptr;
157 
hasOutlinedPartsInfo158     bool hasOutlinedParts() const { return OutlinedParts != nullptr; }
isPostSplitInfo159     bool isPostSplit() const { return Resumers != nullptr; }
isPreSplitInfo160     bool isPreSplit() const { return !isPostSplit(); }
161   };
getInfo()162   Info getInfo() const {
163     Info Result;
164     auto *GV = dyn_cast<GlobalVariable>(getRawInfo());
165     if (!GV)
166       return Result;
167 
168     assert(GV->isConstant() && GV->hasDefinitiveInitializer());
169     Constant *Initializer = GV->getInitializer();
170     if ((Result.OutlinedParts = dyn_cast<ConstantStruct>(Initializer)))
171       return Result;
172 
173     Result.Resumers = cast<ConstantArray>(Initializer);
174     return Result;
175   }
getRawInfo()176   Constant *getRawInfo() const {
177     return cast<Constant>(getArgOperand(InfoArg)->stripPointerCasts());
178   }
179 
setInfo(Constant * C)180   void setInfo(Constant *C) { setArgOperand(InfoArg, C); }
181 
getCoroutine()182   Function *getCoroutine() const {
183     return cast<Function>(getArgOperand(CoroutineArg)->stripPointerCasts());
184   }
setCoroutineSelf()185   void setCoroutineSelf() {
186     assert(isa<ConstantPointerNull>(getArgOperand(CoroutineArg)) &&
187            "Coroutine argument is already assigned");
188     setArgOperand(CoroutineArg, getFunction());
189   }
190 
191   // Methods to support type inquiry through isa, cast, and dyn_cast:
classof(const IntrinsicInst * I)192   static bool classof(const IntrinsicInst *I) {
193     return I->getIntrinsicID() == Intrinsic::coro_id;
194   }
classof(const Value * V)195   static bool classof(const Value *V) {
196     return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
197   }
198 };
199 
200 /// This represents either the llvm.coro.id.retcon or
201 /// llvm.coro.id.retcon.once instruction.
202 class LLVM_LIBRARY_VISIBILITY AnyCoroIdRetconInst : public AnyCoroIdInst {
203   enum { SizeArg, AlignArg, StorageArg, PrototypeArg, AllocArg, DeallocArg };
204 
205 public:
206   void checkWellFormed() const;
207 
getStorageSize()208   uint64_t getStorageSize() const {
209     return cast<ConstantInt>(getArgOperand(SizeArg))->getZExtValue();
210   }
211 
getStorageAlignment()212   Align getStorageAlignment() const {
213     return cast<ConstantInt>(getArgOperand(AlignArg))->getAlignValue();
214   }
215 
getStorage()216   Value *getStorage() const {
217     return getArgOperand(StorageArg);
218   }
219 
220   /// Return the prototype for the continuation function.  The type,
221   /// attributes, and calling convention of the continuation function(s)
222   /// are taken from this declaration.
getPrototype()223   Function *getPrototype() const {
224     return cast<Function>(getArgOperand(PrototypeArg)->stripPointerCasts());
225   }
226 
227   /// Return the function to use for allocating memory.
getAllocFunction()228   Function *getAllocFunction() const {
229     return cast<Function>(getArgOperand(AllocArg)->stripPointerCasts());
230   }
231 
232   /// Return the function to use for deallocating memory.
getDeallocFunction()233   Function *getDeallocFunction() const {
234     return cast<Function>(getArgOperand(DeallocArg)->stripPointerCasts());
235   }
236 
237   // Methods to support type inquiry through isa, cast, and dyn_cast:
classof(const IntrinsicInst * I)238   static bool classof(const IntrinsicInst *I) {
239     auto ID = I->getIntrinsicID();
240     return ID == Intrinsic::coro_id_retcon
241         || ID == Intrinsic::coro_id_retcon_once;
242   }
classof(const Value * V)243   static bool classof(const Value *V) {
244     return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
245   }
246 };
247 
248 /// This represents the llvm.coro.id.retcon instruction.
249 class LLVM_LIBRARY_VISIBILITY CoroIdRetconInst
250     : public AnyCoroIdRetconInst {
251 public:
252   // Methods to support type inquiry through isa, cast, and dyn_cast:
classof(const IntrinsicInst * I)253   static bool classof(const IntrinsicInst *I) {
254     return I->getIntrinsicID() == Intrinsic::coro_id_retcon;
255   }
classof(const Value * V)256   static bool classof(const Value *V) {
257     return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
258   }
259 };
260 
261 /// This represents the llvm.coro.id.retcon.once instruction.
262 class LLVM_LIBRARY_VISIBILITY CoroIdRetconOnceInst
263     : public AnyCoroIdRetconInst {
264 public:
265   // Methods to support type inquiry through isa, cast, and dyn_cast:
classof(const IntrinsicInst * I)266   static bool classof(const IntrinsicInst *I) {
267     return I->getIntrinsicID() == Intrinsic::coro_id_retcon_once;
268   }
classof(const Value * V)269   static bool classof(const Value *V) {
270     return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
271   }
272 };
273 
274 /// This represents the llvm.coro.id.async instruction.
275 class LLVM_LIBRARY_VISIBILITY CoroIdAsyncInst : public AnyCoroIdInst {
276   enum { SizeArg, AlignArg, StorageArg, AsyncFuncPtrArg };
277 
278 public:
279   void checkWellFormed() const;
280 
281   /// The initial async function context size. The fields of which are reserved
282   /// for use by the frontend. The frame will be allocated as a tail of this
283   /// context.
getStorageSize()284   uint64_t getStorageSize() const {
285     return cast<ConstantInt>(getArgOperand(SizeArg))->getZExtValue();
286   }
287 
288   /// The alignment of the initial async function context.
getStorageAlignment()289   Align getStorageAlignment() const {
290     return cast<ConstantInt>(getArgOperand(AlignArg))->getAlignValue();
291   }
292 
293   /// The async context parameter.
getStorage()294   Value *getStorage() const {
295     return getParent()->getParent()->getArg(getStorageArgumentIndex());
296   }
297 
getStorageArgumentIndex()298   unsigned getStorageArgumentIndex() const {
299     auto *Arg = cast<ConstantInt>(getArgOperand(StorageArg));
300     return Arg->getZExtValue();
301   }
302 
303   /// Return the async function pointer address. This should be the address of
304   /// a async function pointer struct for the current async function.
305   /// struct async_function_pointer {
306   ///   uint32_t context_size;
307   ///   uint32_t relative_async_function_pointer;
308   ///  };
getAsyncFunctionPointer()309   GlobalVariable *getAsyncFunctionPointer() const {
310     return cast<GlobalVariable>(
311         getArgOperand(AsyncFuncPtrArg)->stripPointerCasts());
312   }
313 
314   // Methods to support type inquiry through isa, cast, and dyn_cast:
classof(const IntrinsicInst * I)315   static bool classof(const IntrinsicInst *I) {
316     auto ID = I->getIntrinsicID();
317     return ID == Intrinsic::coro_id_async;
318   }
319 
classof(const Value * V)320   static bool classof(const Value *V) {
321     return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
322   }
323 };
324 
325 /// This represents the llvm.coro.context.alloc instruction.
326 class LLVM_LIBRARY_VISIBILITY CoroAsyncContextAllocInst : public IntrinsicInst {
327   enum { AsyncFuncPtrArg };
328 
329 public:
getAsyncFunctionPointer()330   GlobalVariable *getAsyncFunctionPointer() const {
331     return cast<GlobalVariable>(
332         getArgOperand(AsyncFuncPtrArg)->stripPointerCasts());
333   }
334 
335   // Methods to support type inquiry through isa, cast, and dyn_cast:
classof(const IntrinsicInst * I)336   static bool classof(const IntrinsicInst *I) {
337     return I->getIntrinsicID() == Intrinsic::coro_async_context_alloc;
338   }
classof(const Value * V)339   static bool classof(const Value *V) {
340     return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
341   }
342 };
343 
344 /// This represents the llvm.coro.context.dealloc instruction.
345 class LLVM_LIBRARY_VISIBILITY CoroAsyncContextDeallocInst
346     : public IntrinsicInst {
347   enum { AsyncContextArg };
348 
349 public:
getAsyncContext()350   Value *getAsyncContext() const {
351     return getArgOperand(AsyncContextArg)->stripPointerCasts();
352   }
353 
354   // Methods to support type inquiry through isa, cast, and dyn_cast:
classof(const IntrinsicInst * I)355   static bool classof(const IntrinsicInst *I) {
356     return I->getIntrinsicID() == Intrinsic::coro_async_context_dealloc;
357   }
classof(const Value * V)358   static bool classof(const Value *V) {
359     return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
360   }
361 };
362 
363 /// This represents the llvm.coro.async.resume instruction.
364 /// During lowering this is replaced by the resume function of a suspend point
365 /// (the continuation function).
366 class LLVM_LIBRARY_VISIBILITY CoroAsyncResumeInst : public IntrinsicInst {
367 public:
368   // Methods to support type inquiry through isa, cast, and dyn_cast:
classof(const IntrinsicInst * I)369   static bool classof(const IntrinsicInst *I) {
370     return I->getIntrinsicID() == Intrinsic::coro_async_resume;
371   }
classof(const Value * V)372   static bool classof(const Value *V) {
373     return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
374   }
375 };
376 
377 /// This represents the llvm.coro.async.size.replace instruction.
378 class LLVM_LIBRARY_VISIBILITY CoroAsyncSizeReplace : public IntrinsicInst {
379 public:
380   // Methods to support type inquiry through isa, cast, and dyn_cast:
classof(const IntrinsicInst * I)381   static bool classof(const IntrinsicInst *I) {
382     return I->getIntrinsicID() == Intrinsic::coro_async_size_replace;
383   }
classof(const Value * V)384   static bool classof(const Value *V) {
385     return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
386   }
387 };
388 
389 /// This represents the llvm.coro.frame instruction.
390 class LLVM_LIBRARY_VISIBILITY CoroFrameInst : public IntrinsicInst {
391 public:
392   // Methods to support type inquiry through isa, cast, and dyn_cast:
classof(const IntrinsicInst * I)393   static bool classof(const IntrinsicInst *I) {
394     return I->getIntrinsicID() == Intrinsic::coro_frame;
395   }
classof(const Value * V)396   static bool classof(const Value *V) {
397     return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
398   }
399 };
400 
401 /// This represents the llvm.coro.free instruction.
402 class LLVM_LIBRARY_VISIBILITY CoroFreeInst : public IntrinsicInst {
403   enum { IdArg, FrameArg };
404 
405 public:
getFrame()406   Value *getFrame() const { return getArgOperand(FrameArg); }
407 
408   // Methods to support type inquiry through isa, cast, and dyn_cast:
classof(const IntrinsicInst * I)409   static bool classof(const IntrinsicInst *I) {
410     return I->getIntrinsicID() == Intrinsic::coro_free;
411   }
classof(const Value * V)412   static bool classof(const Value *V) {
413     return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
414   }
415 };
416 
417 /// This class represents the llvm.coro.begin instruction.
418 class LLVM_LIBRARY_VISIBILITY CoroBeginInst : public IntrinsicInst {
419   enum { IdArg, MemArg };
420 
421 public:
getId()422   AnyCoroIdInst *getId() const {
423     return cast<AnyCoroIdInst>(getArgOperand(IdArg));
424   }
425 
getMem()426   Value *getMem() const { return getArgOperand(MemArg); }
427 
428   // Methods for support type inquiry through isa, cast, and dyn_cast:
classof(const IntrinsicInst * I)429   static bool classof(const IntrinsicInst *I) {
430     return I->getIntrinsicID() == Intrinsic::coro_begin;
431   }
classof(const Value * V)432   static bool classof(const Value *V) {
433     return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
434   }
435 };
436 
437 /// This represents the llvm.coro.save instruction.
438 class LLVM_LIBRARY_VISIBILITY CoroSaveInst : public IntrinsicInst {
439 public:
440   // Methods to support type inquiry through isa, cast, and dyn_cast:
classof(const IntrinsicInst * I)441   static bool classof(const IntrinsicInst *I) {
442     return I->getIntrinsicID() == Intrinsic::coro_save;
443   }
classof(const Value * V)444   static bool classof(const Value *V) {
445     return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
446   }
447 };
448 
449 /// This represents the llvm.coro.promise instruction.
450 class LLVM_LIBRARY_VISIBILITY CoroPromiseInst : public IntrinsicInst {
451   enum { FrameArg, AlignArg, FromArg };
452 
453 public:
454   /// Are we translating from the frame to the promise (false) or from
455   /// the promise to the frame (true)?
isFromPromise()456   bool isFromPromise() const {
457     return cast<Constant>(getArgOperand(FromArg))->isOneValue();
458   }
459 
460   /// The required alignment of the promise.  This must match the
461   /// alignment of the promise alloca in the coroutine.
getAlignment()462   Align getAlignment() const {
463     return cast<ConstantInt>(getArgOperand(AlignArg))->getAlignValue();
464   }
465 
466   // Methods to support type inquiry through isa, cast, and dyn_cast:
classof(const IntrinsicInst * I)467   static bool classof(const IntrinsicInst *I) {
468     return I->getIntrinsicID() == Intrinsic::coro_promise;
469   }
classof(const Value * V)470   static bool classof(const Value *V) {
471     return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
472   }
473 };
474 
475 class LLVM_LIBRARY_VISIBILITY AnyCoroSuspendInst : public IntrinsicInst {
476 public:
477   CoroSaveInst *getCoroSave() const;
478 
479   // Methods to support type inquiry through isa, cast, and dyn_cast:
classof(const IntrinsicInst * I)480   static bool classof(const IntrinsicInst *I) {
481     return I->getIntrinsicID() == Intrinsic::coro_suspend ||
482            I->getIntrinsicID() == Intrinsic::coro_suspend_async ||
483            I->getIntrinsicID() == Intrinsic::coro_suspend_retcon;
484   }
classof(const Value * V)485   static bool classof(const Value *V) {
486     return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
487   }
488 };
489 
490 /// This represents the llvm.coro.suspend instruction.
491 class LLVM_LIBRARY_VISIBILITY CoroSuspendInst : public AnyCoroSuspendInst {
492   enum { SaveArg, FinalArg };
493 
494 public:
getCoroSave()495   CoroSaveInst *getCoroSave() const {
496     Value *Arg = getArgOperand(SaveArg);
497     if (auto *SI = dyn_cast<CoroSaveInst>(Arg))
498       return SI;
499     assert(isa<ConstantTokenNone>(Arg));
500     return nullptr;
501   }
502 
isFinal()503   bool isFinal() const {
504     return cast<Constant>(getArgOperand(FinalArg))->isOneValue();
505   }
506 
507   // Methods to support type inquiry through isa, cast, and dyn_cast:
classof(const IntrinsicInst * I)508   static bool classof(const IntrinsicInst *I) {
509     return I->getIntrinsicID() == Intrinsic::coro_suspend;
510   }
classof(const Value * V)511   static bool classof(const Value *V) {
512     return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
513   }
514 };
515 
getCoroSave()516 inline CoroSaveInst *AnyCoroSuspendInst::getCoroSave() const {
517   if (auto Suspend = dyn_cast<CoroSuspendInst>(this))
518     return Suspend->getCoroSave();
519   return nullptr;
520 }
521 
522 /// This represents the llvm.coro.suspend.async instruction.
523 class LLVM_LIBRARY_VISIBILITY CoroSuspendAsyncInst : public AnyCoroSuspendInst {
524 public:
525   enum {
526     StorageArgNoArg,
527     ResumeFunctionArg,
528     AsyncContextProjectionArg,
529     MustTailCallFuncArg
530   };
531 
532   void checkWellFormed() const;
533 
getStorageArgumentIndex()534   unsigned getStorageArgumentIndex() const {
535     auto *Arg = cast<ConstantInt>(getArgOperand(StorageArgNoArg));
536     return Arg->getZExtValue();
537   }
538 
getAsyncContextProjectionFunction()539   Function *getAsyncContextProjectionFunction() const {
540     return cast<Function>(
541         getArgOperand(AsyncContextProjectionArg)->stripPointerCasts());
542   }
543 
getResumeFunction()544   CoroAsyncResumeInst *getResumeFunction() const {
545     return cast<CoroAsyncResumeInst>(
546         getArgOperand(ResumeFunctionArg)->stripPointerCasts());
547   }
548 
getMustTailCallFunction()549   Function *getMustTailCallFunction() const {
550     return cast<Function>(
551         getArgOperand(MustTailCallFuncArg)->stripPointerCasts());
552   }
553 
554   // Methods to support type inquiry through isa, cast, and dyn_cast:
classof(const IntrinsicInst * I)555   static bool classof(const IntrinsicInst *I) {
556     return I->getIntrinsicID() == Intrinsic::coro_suspend_async;
557   }
classof(const Value * V)558   static bool classof(const Value *V) {
559     return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
560   }
561 };
562 
563 /// This represents the llvm.coro.suspend.retcon instruction.
564 class LLVM_LIBRARY_VISIBILITY CoroSuspendRetconInst : public AnyCoroSuspendInst {
565 public:
value_begin()566   op_iterator value_begin() { return arg_begin(); }
value_begin()567   const_op_iterator value_begin() const { return arg_begin(); }
568 
value_end()569   op_iterator value_end() { return arg_end(); }
value_end()570   const_op_iterator value_end() const { return arg_end(); }
571 
value_operands()572   iterator_range<op_iterator> value_operands() {
573     return make_range(value_begin(), value_end());
574   }
value_operands()575   iterator_range<const_op_iterator> value_operands() const {
576     return make_range(value_begin(), value_end());
577   }
578 
579   // Methods to support type inquiry through isa, cast, and dyn_cast:
classof(const IntrinsicInst * I)580   static bool classof(const IntrinsicInst *I) {
581     return I->getIntrinsicID() == Intrinsic::coro_suspend_retcon;
582   }
classof(const Value * V)583   static bool classof(const Value *V) {
584     return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
585   }
586 };
587 
588 /// This represents the llvm.coro.size instruction.
589 class LLVM_LIBRARY_VISIBILITY CoroSizeInst : public IntrinsicInst {
590 public:
591   // Methods to support type inquiry through isa, cast, and dyn_cast:
classof(const IntrinsicInst * I)592   static bool classof(const IntrinsicInst *I) {
593     return I->getIntrinsicID() == Intrinsic::coro_size;
594   }
classof(const Value * V)595   static bool classof(const Value *V) {
596     return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
597   }
598 };
599 
600 /// This represents the llvm.coro.align instruction.
601 class LLVM_LIBRARY_VISIBILITY CoroAlignInst : public IntrinsicInst {
602 public:
603   // Methods to support type inquiry through isa, cast, and dyn_cast:
classof(const IntrinsicInst * I)604   static bool classof(const IntrinsicInst *I) {
605     return I->getIntrinsicID() == Intrinsic::coro_align;
606   }
classof(const Value * V)607   static bool classof(const Value *V) {
608     return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
609   }
610 };
611 
612 /// This represents the llvm.end.results instruction.
613 class LLVM_LIBRARY_VISIBILITY CoroEndResults : public IntrinsicInst {
614 public:
retval_begin()615   op_iterator retval_begin() { return arg_begin(); }
retval_begin()616   const_op_iterator retval_begin() const { return arg_begin(); }
617 
retval_end()618   op_iterator retval_end() { return arg_end(); }
retval_end()619   const_op_iterator retval_end() const { return arg_end(); }
620 
return_values()621   iterator_range<op_iterator> return_values() {
622     return make_range(retval_begin(), retval_end());
623   }
return_values()624   iterator_range<const_op_iterator> return_values() const {
625     return make_range(retval_begin(), retval_end());
626   }
627 
numReturns()628   unsigned numReturns() const {
629     return std::distance(retval_begin(), retval_end());
630   }
631 
632   // Methods to support type inquiry through isa, cast, and dyn_cast:
classof(const IntrinsicInst * I)633   static bool classof(const IntrinsicInst *I) {
634     return I->getIntrinsicID() == Intrinsic::coro_end_results;
635   }
classof(const Value * V)636   static bool classof(const Value *V) {
637     return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
638   }
639 };
640 
641 class LLVM_LIBRARY_VISIBILITY AnyCoroEndInst : public IntrinsicInst {
642   enum { FrameArg, UnwindArg, TokenArg };
643 
644 public:
isFallthrough()645   bool isFallthrough() const { return !isUnwind(); }
isUnwind()646   bool isUnwind() const {
647     return cast<Constant>(getArgOperand(UnwindArg))->isOneValue();
648   }
649 
hasResults()650   bool hasResults() const {
651     return !isa<ConstantTokenNone>(getArgOperand(TokenArg));
652   }
653 
getResults()654   CoroEndResults *getResults() const {
655     assert(hasResults());
656     return cast<CoroEndResults>(getArgOperand(TokenArg));
657   }
658 
659   // Methods to support type inquiry through isa, cast, and dyn_cast:
classof(const IntrinsicInst * I)660   static bool classof(const IntrinsicInst *I) {
661     auto ID = I->getIntrinsicID();
662     return ID == Intrinsic::coro_end || ID == Intrinsic::coro_end_async;
663   }
classof(const Value * V)664   static bool classof(const Value *V) {
665     return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
666   }
667 };
668 
669 /// This represents the llvm.coro.end instruction.
670 class LLVM_LIBRARY_VISIBILITY CoroEndInst : public AnyCoroEndInst {
671 public:
672   // Methods to support type inquiry through isa, cast, and dyn_cast:
classof(const IntrinsicInst * I)673   static bool classof(const IntrinsicInst *I) {
674     return I->getIntrinsicID() == Intrinsic::coro_end;
675   }
classof(const Value * V)676   static bool classof(const Value *V) {
677     return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
678   }
679 };
680 
681 /// This represents the llvm.coro.end instruction.
682 class LLVM_LIBRARY_VISIBILITY CoroAsyncEndInst : public AnyCoroEndInst {
683   enum { FrameArg, UnwindArg, MustTailCallFuncArg };
684 
685 public:
686   void checkWellFormed() const;
687 
getMustTailCallFunction()688   Function *getMustTailCallFunction() const {
689     if (arg_size() < 3)
690       return nullptr;
691 
692     return cast<Function>(
693         getArgOperand(MustTailCallFuncArg)->stripPointerCasts());
694   }
695 
696   // Methods to support type inquiry through isa, cast, and dyn_cast:
classof(const IntrinsicInst * I)697   static bool classof(const IntrinsicInst *I) {
698     return I->getIntrinsicID() == Intrinsic::coro_end_async;
699   }
classof(const Value * V)700   static bool classof(const Value *V) {
701     return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
702   }
703 };
704 
705 /// This represents the llvm.coro.alloca.alloc instruction.
706 class LLVM_LIBRARY_VISIBILITY CoroAllocaAllocInst : public IntrinsicInst {
707   enum { SizeArg, AlignArg };
708 public:
getSize()709   Value *getSize() const {
710     return getArgOperand(SizeArg);
711   }
getAlignment()712   Align getAlignment() const {
713     return cast<ConstantInt>(getArgOperand(AlignArg))->getAlignValue();
714   }
715 
716   // Methods to support type inquiry through isa, cast, and dyn_cast:
classof(const IntrinsicInst * I)717   static bool classof(const IntrinsicInst *I) {
718     return I->getIntrinsicID() == Intrinsic::coro_alloca_alloc;
719   }
classof(const Value * V)720   static bool classof(const Value *V) {
721     return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
722   }
723 };
724 
725 /// This represents the llvm.coro.alloca.get instruction.
726 class LLVM_LIBRARY_VISIBILITY CoroAllocaGetInst : public IntrinsicInst {
727   enum { AllocArg };
728 public:
getAlloc()729   CoroAllocaAllocInst *getAlloc() const {
730     return cast<CoroAllocaAllocInst>(getArgOperand(AllocArg));
731   }
732 
733   // Methods to support type inquiry through isa, cast, and dyn_cast:
classof(const IntrinsicInst * I)734   static bool classof(const IntrinsicInst *I) {
735     return I->getIntrinsicID() == Intrinsic::coro_alloca_get;
736   }
classof(const Value * V)737   static bool classof(const Value *V) {
738     return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
739   }
740 };
741 
742 /// This represents the llvm.coro.alloca.free instruction.
743 class LLVM_LIBRARY_VISIBILITY CoroAllocaFreeInst : public IntrinsicInst {
744   enum { AllocArg };
745 public:
getAlloc()746   CoroAllocaAllocInst *getAlloc() const {
747     return cast<CoroAllocaAllocInst>(getArgOperand(AllocArg));
748   }
749 
750   // Methods to support type inquiry through isa, cast, and dyn_cast:
classof(const IntrinsicInst * I)751   static bool classof(const IntrinsicInst *I) {
752     return I->getIntrinsicID() == Intrinsic::coro_alloca_free;
753   }
classof(const Value * V)754   static bool classof(const Value *V) {
755     return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
756   }
757 };
758 
759 } // End namespace llvm.
760 
761 #endif
762