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 
48   Value *getFrame() const { return getArgOperand(FrameArg); }
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 
56   ConstantInt *getRawIndex() const {
57     return cast<ConstantInt>(getArgOperand(IndexArg));
58   }
59 
60   // Methods to support type inquiry through isa, cast, and dyn_cast:
61   static bool classof(const IntrinsicInst *I) {
62     return I->getIntrinsicID() == Intrinsic::coro_subfn_addr;
63   }
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:
73   static bool classof(const IntrinsicInst *I) {
74     return I->getIntrinsicID() == Intrinsic::coro_alloc;
75   }
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:
84   CoroAllocInst *getCoroAlloc() {
85     for (User *U : users())
86       if (auto *CA = dyn_cast<CoroAllocInst>(U))
87         return CA;
88     return nullptr;
89   }
90 
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:
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 
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:
117   AllocaInst *getPromise() const {
118     Value *Arg = getArgOperand(PromiseArg);
119     return isa<ConstantPointerNull>(Arg)
120                ? nullptr
121                : cast<AllocaInst>(Arg->stripPointerCasts());
122   }
123 
124   void clearPromise() {
125     Value *Arg = getArgOperand(PromiseArg);
126     setArgOperand(PromiseArg,
127                   ConstantPointerNull::get(Type::getInt8PtrTy(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 
158     bool hasOutlinedParts() const { return OutlinedParts != nullptr; }
159     bool isPostSplit() const { return Resumers != nullptr; }
160     bool isPreSplit() const { return !isPostSplit(); }
161   };
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   }
176   Constant *getRawInfo() const {
177     return cast<Constant>(getArgOperand(InfoArg)->stripPointerCasts());
178   }
179 
180   void setInfo(Constant *C) { setArgOperand(InfoArg, C); }
181 
182   Function *getCoroutine() const {
183     return cast<Function>(getArgOperand(CoroutineArg)->stripPointerCasts());
184   }
185   void setCoroutineSelf() {
186     assert(isa<ConstantPointerNull>(getArgOperand(CoroutineArg)) &&
187            "Coroutine argument is already assigned");
188     auto *const Int8PtrTy = Type::getInt8PtrTy(getContext());
189     setArgOperand(CoroutineArg,
190                   ConstantExpr::getBitCast(getFunction(), Int8PtrTy));
191   }
192 
193   // Methods to support type inquiry through isa, cast, and dyn_cast:
194   static bool classof(const IntrinsicInst *I) {
195     return I->getIntrinsicID() == Intrinsic::coro_id;
196   }
197   static bool classof(const Value *V) {
198     return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
199   }
200 };
201 
202 /// This represents either the llvm.coro.id.retcon or
203 /// llvm.coro.id.retcon.once instruction.
204 class LLVM_LIBRARY_VISIBILITY AnyCoroIdRetconInst : public AnyCoroIdInst {
205   enum { SizeArg, AlignArg, StorageArg, PrototypeArg, AllocArg, DeallocArg };
206 
207 public:
208   void checkWellFormed() const;
209 
210   uint64_t getStorageSize() const {
211     return cast<ConstantInt>(getArgOperand(SizeArg))->getZExtValue();
212   }
213 
214   Align getStorageAlignment() const {
215     return cast<ConstantInt>(getArgOperand(AlignArg))->getAlignValue();
216   }
217 
218   Value *getStorage() const {
219     return getArgOperand(StorageArg);
220   }
221 
222   /// Return the prototype for the continuation function.  The type,
223   /// attributes, and calling convention of the continuation function(s)
224   /// are taken from this declaration.
225   Function *getPrototype() const {
226     return cast<Function>(getArgOperand(PrototypeArg)->stripPointerCasts());
227   }
228 
229   /// Return the function to use for allocating memory.
230   Function *getAllocFunction() const {
231     return cast<Function>(getArgOperand(AllocArg)->stripPointerCasts());
232   }
233 
234   /// Return the function to use for deallocating memory.
235   Function *getDeallocFunction() const {
236     return cast<Function>(getArgOperand(DeallocArg)->stripPointerCasts());
237   }
238 
239   // Methods to support type inquiry through isa, cast, and dyn_cast:
240   static bool classof(const IntrinsicInst *I) {
241     auto ID = I->getIntrinsicID();
242     return ID == Intrinsic::coro_id_retcon
243         || ID == Intrinsic::coro_id_retcon_once;
244   }
245   static bool classof(const Value *V) {
246     return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
247   }
248 };
249 
250 /// This represents the llvm.coro.id.retcon instruction.
251 class LLVM_LIBRARY_VISIBILITY CoroIdRetconInst
252     : public AnyCoroIdRetconInst {
253 public:
254   // Methods to support type inquiry through isa, cast, and dyn_cast:
255   static bool classof(const IntrinsicInst *I) {
256     return I->getIntrinsicID() == Intrinsic::coro_id_retcon;
257   }
258   static bool classof(const Value *V) {
259     return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
260   }
261 };
262 
263 /// This represents the llvm.coro.id.retcon.once instruction.
264 class LLVM_LIBRARY_VISIBILITY CoroIdRetconOnceInst
265     : public AnyCoroIdRetconInst {
266 public:
267   // Methods to support type inquiry through isa, cast, and dyn_cast:
268   static bool classof(const IntrinsicInst *I) {
269     return I->getIntrinsicID() == Intrinsic::coro_id_retcon_once;
270   }
271   static bool classof(const Value *V) {
272     return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
273   }
274 };
275 
276 /// This represents the llvm.coro.id.async instruction.
277 class LLVM_LIBRARY_VISIBILITY CoroIdAsyncInst : public AnyCoroIdInst {
278   enum { SizeArg, AlignArg, StorageArg, AsyncFuncPtrArg };
279 
280 public:
281   void checkWellFormed() const;
282 
283   /// The initial async function context size. The fields of which are reserved
284   /// for use by the frontend. The frame will be allocated as a tail of this
285   /// context.
286   uint64_t getStorageSize() const {
287     return cast<ConstantInt>(getArgOperand(SizeArg))->getZExtValue();
288   }
289 
290   /// The alignment of the initial async function context.
291   Align getStorageAlignment() const {
292     return cast<ConstantInt>(getArgOperand(AlignArg))->getAlignValue();
293   }
294 
295   /// The async context parameter.
296   Value *getStorage() const {
297     return getParent()->getParent()->getArg(getStorageArgumentIndex());
298   }
299 
300   unsigned getStorageArgumentIndex() const {
301     auto *Arg = cast<ConstantInt>(getArgOperand(StorageArg));
302     return Arg->getZExtValue();
303   }
304 
305   /// Return the async function pointer address. This should be the address of
306   /// a async function pointer struct for the current async function.
307   /// struct async_function_pointer {
308   ///   uint32_t context_size;
309   ///   uint32_t relative_async_function_pointer;
310   ///  };
311   GlobalVariable *getAsyncFunctionPointer() const {
312     return cast<GlobalVariable>(
313         getArgOperand(AsyncFuncPtrArg)->stripPointerCasts());
314   }
315 
316   // Methods to support type inquiry through isa, cast, and dyn_cast:
317   static bool classof(const IntrinsicInst *I) {
318     auto ID = I->getIntrinsicID();
319     return ID == Intrinsic::coro_id_async;
320   }
321 
322   static bool classof(const Value *V) {
323     return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
324   }
325 };
326 
327 /// This represents the llvm.coro.context.alloc instruction.
328 class LLVM_LIBRARY_VISIBILITY CoroAsyncContextAllocInst : public IntrinsicInst {
329   enum { AsyncFuncPtrArg };
330 
331 public:
332   GlobalVariable *getAsyncFunctionPointer() const {
333     return cast<GlobalVariable>(
334         getArgOperand(AsyncFuncPtrArg)->stripPointerCasts());
335   }
336 
337   // Methods to support type inquiry through isa, cast, and dyn_cast:
338   static bool classof(const IntrinsicInst *I) {
339     return I->getIntrinsicID() == Intrinsic::coro_async_context_alloc;
340   }
341   static bool classof(const Value *V) {
342     return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
343   }
344 };
345 
346 /// This represents the llvm.coro.context.dealloc instruction.
347 class LLVM_LIBRARY_VISIBILITY CoroAsyncContextDeallocInst
348     : public IntrinsicInst {
349   enum { AsyncContextArg };
350 
351 public:
352   Value *getAsyncContext() const {
353     return getArgOperand(AsyncContextArg)->stripPointerCasts();
354   }
355 
356   // Methods to support type inquiry through isa, cast, and dyn_cast:
357   static bool classof(const IntrinsicInst *I) {
358     return I->getIntrinsicID() == Intrinsic::coro_async_context_dealloc;
359   }
360   static bool classof(const Value *V) {
361     return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
362   }
363 };
364 
365 /// This represents the llvm.coro.async.resume instruction.
366 /// During lowering this is replaced by the resume function of a suspend point
367 /// (the continuation function).
368 class LLVM_LIBRARY_VISIBILITY CoroAsyncResumeInst : public IntrinsicInst {
369 public:
370   // Methods to support type inquiry through isa, cast, and dyn_cast:
371   static bool classof(const IntrinsicInst *I) {
372     return I->getIntrinsicID() == Intrinsic::coro_async_resume;
373   }
374   static bool classof(const Value *V) {
375     return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
376   }
377 };
378 
379 /// This represents the llvm.coro.async.size.replace instruction.
380 class LLVM_LIBRARY_VISIBILITY CoroAsyncSizeReplace : public IntrinsicInst {
381 public:
382   // Methods to support type inquiry through isa, cast, and dyn_cast:
383   static bool classof(const IntrinsicInst *I) {
384     return I->getIntrinsicID() == Intrinsic::coro_async_size_replace;
385   }
386   static bool classof(const Value *V) {
387     return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
388   }
389 };
390 
391 /// This represents the llvm.coro.frame instruction.
392 class LLVM_LIBRARY_VISIBILITY CoroFrameInst : public IntrinsicInst {
393 public:
394   // Methods to support type inquiry through isa, cast, and dyn_cast:
395   static bool classof(const IntrinsicInst *I) {
396     return I->getIntrinsicID() == Intrinsic::coro_frame;
397   }
398   static bool classof(const Value *V) {
399     return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
400   }
401 };
402 
403 /// This represents the llvm.coro.free instruction.
404 class LLVM_LIBRARY_VISIBILITY CoroFreeInst : public IntrinsicInst {
405   enum { IdArg, FrameArg };
406 
407 public:
408   Value *getFrame() const { return getArgOperand(FrameArg); }
409 
410   // Methods to support type inquiry through isa, cast, and dyn_cast:
411   static bool classof(const IntrinsicInst *I) {
412     return I->getIntrinsicID() == Intrinsic::coro_free;
413   }
414   static bool classof(const Value *V) {
415     return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
416   }
417 };
418 
419 /// This class represents the llvm.coro.begin instruction.
420 class LLVM_LIBRARY_VISIBILITY CoroBeginInst : public IntrinsicInst {
421   enum { IdArg, MemArg };
422 
423 public:
424   AnyCoroIdInst *getId() const {
425     return cast<AnyCoroIdInst>(getArgOperand(IdArg));
426   }
427 
428   Value *getMem() const { return getArgOperand(MemArg); }
429 
430   // Methods for support type inquiry through isa, cast, and dyn_cast:
431   static bool classof(const IntrinsicInst *I) {
432     return I->getIntrinsicID() == Intrinsic::coro_begin;
433   }
434   static bool classof(const Value *V) {
435     return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
436   }
437 };
438 
439 /// This represents the llvm.coro.save instruction.
440 class LLVM_LIBRARY_VISIBILITY CoroSaveInst : public IntrinsicInst {
441 public:
442   // Methods to support type inquiry through isa, cast, and dyn_cast:
443   static bool classof(const IntrinsicInst *I) {
444     return I->getIntrinsicID() == Intrinsic::coro_save;
445   }
446   static bool classof(const Value *V) {
447     return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
448   }
449 };
450 
451 /// This represents the llvm.coro.promise instruction.
452 class LLVM_LIBRARY_VISIBILITY CoroPromiseInst : public IntrinsicInst {
453   enum { FrameArg, AlignArg, FromArg };
454 
455 public:
456   /// Are we translating from the frame to the promise (false) or from
457   /// the promise to the frame (true)?
458   bool isFromPromise() const {
459     return cast<Constant>(getArgOperand(FromArg))->isOneValue();
460   }
461 
462   /// The required alignment of the promise.  This must match the
463   /// alignment of the promise alloca in the coroutine.
464   Align getAlignment() const {
465     return cast<ConstantInt>(getArgOperand(AlignArg))->getAlignValue();
466   }
467 
468   // Methods to support type inquiry through isa, cast, and dyn_cast:
469   static bool classof(const IntrinsicInst *I) {
470     return I->getIntrinsicID() == Intrinsic::coro_promise;
471   }
472   static bool classof(const Value *V) {
473     return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
474   }
475 };
476 
477 class LLVM_LIBRARY_VISIBILITY AnyCoroSuspendInst : public IntrinsicInst {
478 public:
479   CoroSaveInst *getCoroSave() const;
480 
481   // Methods to support type inquiry through isa, cast, and dyn_cast:
482   static bool classof(const IntrinsicInst *I) {
483     return I->getIntrinsicID() == Intrinsic::coro_suspend ||
484            I->getIntrinsicID() == Intrinsic::coro_suspend_async ||
485            I->getIntrinsicID() == Intrinsic::coro_suspend_retcon;
486   }
487   static bool classof(const Value *V) {
488     return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
489   }
490 };
491 
492 /// This represents the llvm.coro.suspend instruction.
493 class LLVM_LIBRARY_VISIBILITY CoroSuspendInst : public AnyCoroSuspendInst {
494   enum { SaveArg, FinalArg };
495 
496 public:
497   CoroSaveInst *getCoroSave() const {
498     Value *Arg = getArgOperand(SaveArg);
499     if (auto *SI = dyn_cast<CoroSaveInst>(Arg))
500       return SI;
501     assert(isa<ConstantTokenNone>(Arg));
502     return nullptr;
503   }
504 
505   bool isFinal() const {
506     return cast<Constant>(getArgOperand(FinalArg))->isOneValue();
507   }
508 
509   // Methods to support type inquiry through isa, cast, and dyn_cast:
510   static bool classof(const IntrinsicInst *I) {
511     return I->getIntrinsicID() == Intrinsic::coro_suspend;
512   }
513   static bool classof(const Value *V) {
514     return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
515   }
516 };
517 
518 inline CoroSaveInst *AnyCoroSuspendInst::getCoroSave() const {
519   if (auto Suspend = dyn_cast<CoroSuspendInst>(this))
520     return Suspend->getCoroSave();
521   return nullptr;
522 }
523 
524 /// This represents the llvm.coro.suspend.async instruction.
525 class LLVM_LIBRARY_VISIBILITY CoroSuspendAsyncInst : public AnyCoroSuspendInst {
526 public:
527   enum {
528     StorageArgNoArg,
529     ResumeFunctionArg,
530     AsyncContextProjectionArg,
531     MustTailCallFuncArg
532   };
533 
534   void checkWellFormed() const;
535 
536   unsigned getStorageArgumentIndex() const {
537     auto *Arg = cast<ConstantInt>(getArgOperand(StorageArgNoArg));
538     return Arg->getZExtValue();
539   }
540 
541   Function *getAsyncContextProjectionFunction() const {
542     return cast<Function>(
543         getArgOperand(AsyncContextProjectionArg)->stripPointerCasts());
544   }
545 
546   CoroAsyncResumeInst *getResumeFunction() const {
547     return cast<CoroAsyncResumeInst>(
548         getArgOperand(ResumeFunctionArg)->stripPointerCasts());
549   }
550 
551   Function *getMustTailCallFunction() const {
552     return cast<Function>(
553         getArgOperand(MustTailCallFuncArg)->stripPointerCasts());
554   }
555 
556   // Methods to support type inquiry through isa, cast, and dyn_cast:
557   static bool classof(const IntrinsicInst *I) {
558     return I->getIntrinsicID() == Intrinsic::coro_suspend_async;
559   }
560   static bool classof(const Value *V) {
561     return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
562   }
563 };
564 
565 /// This represents the llvm.coro.suspend.retcon instruction.
566 class LLVM_LIBRARY_VISIBILITY CoroSuspendRetconInst : public AnyCoroSuspendInst {
567 public:
568   op_iterator value_begin() { return arg_begin(); }
569   const_op_iterator value_begin() const { return arg_begin(); }
570 
571   op_iterator value_end() { return arg_end(); }
572   const_op_iterator value_end() const { return arg_end(); }
573 
574   iterator_range<op_iterator> value_operands() {
575     return make_range(value_begin(), value_end());
576   }
577   iterator_range<const_op_iterator> value_operands() const {
578     return make_range(value_begin(), value_end());
579   }
580 
581   // Methods to support type inquiry through isa, cast, and dyn_cast:
582   static bool classof(const IntrinsicInst *I) {
583     return I->getIntrinsicID() == Intrinsic::coro_suspend_retcon;
584   }
585   static bool classof(const Value *V) {
586     return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
587   }
588 };
589 
590 /// This represents the llvm.coro.size instruction.
591 class LLVM_LIBRARY_VISIBILITY CoroSizeInst : public IntrinsicInst {
592 public:
593   // Methods to support type inquiry through isa, cast, and dyn_cast:
594   static bool classof(const IntrinsicInst *I) {
595     return I->getIntrinsicID() == Intrinsic::coro_size;
596   }
597   static bool classof(const Value *V) {
598     return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
599   }
600 };
601 
602 class LLVM_LIBRARY_VISIBILITY AnyCoroEndInst : public IntrinsicInst {
603   enum { FrameArg, UnwindArg };
604 
605 public:
606   bool isFallthrough() const { return !isUnwind(); }
607   bool isUnwind() const {
608     return cast<Constant>(getArgOperand(UnwindArg))->isOneValue();
609   }
610 
611   // Methods to support type inquiry through isa, cast, and dyn_cast:
612   static bool classof(const IntrinsicInst *I) {
613     auto ID = I->getIntrinsicID();
614     return ID == Intrinsic::coro_end || ID == Intrinsic::coro_end_async;
615   }
616   static bool classof(const Value *V) {
617     return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
618   }
619 };
620 
621 /// This represents the llvm.coro.end instruction.
622 class LLVM_LIBRARY_VISIBILITY CoroEndInst : public AnyCoroEndInst {
623 public:
624   // Methods to support type inquiry through isa, cast, and dyn_cast:
625   static bool classof(const IntrinsicInst *I) {
626     return I->getIntrinsicID() == Intrinsic::coro_end;
627   }
628   static bool classof(const Value *V) {
629     return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
630   }
631 };
632 
633 /// This represents the llvm.coro.end instruction.
634 class LLVM_LIBRARY_VISIBILITY CoroAsyncEndInst : public AnyCoroEndInst {
635   enum { FrameArg, UnwindArg, MustTailCallFuncArg };
636 
637 public:
638   void checkWellFormed() const;
639 
640   Function *getMustTailCallFunction() const {
641     if (getNumArgOperands() < 3)
642       return nullptr;
643 
644     return cast<Function>(
645         getArgOperand(MustTailCallFuncArg)->stripPointerCasts());
646   }
647 
648   // Methods to support type inquiry through isa, cast, and dyn_cast:
649   static bool classof(const IntrinsicInst *I) {
650     return I->getIntrinsicID() == Intrinsic::coro_end_async;
651   }
652   static bool classof(const Value *V) {
653     return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
654   }
655 };
656 
657 /// This represents the llvm.coro.alloca.alloc instruction.
658 class LLVM_LIBRARY_VISIBILITY CoroAllocaAllocInst : public IntrinsicInst {
659   enum { SizeArg, AlignArg };
660 public:
661   Value *getSize() const {
662     return getArgOperand(SizeArg);
663   }
664   Align getAlignment() const {
665     return cast<ConstantInt>(getArgOperand(AlignArg))->getAlignValue();
666   }
667 
668   // Methods to support type inquiry through isa, cast, and dyn_cast:
669   static bool classof(const IntrinsicInst *I) {
670     return I->getIntrinsicID() == Intrinsic::coro_alloca_alloc;
671   }
672   static bool classof(const Value *V) {
673     return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
674   }
675 };
676 
677 /// This represents the llvm.coro.alloca.get instruction.
678 class LLVM_LIBRARY_VISIBILITY CoroAllocaGetInst : public IntrinsicInst {
679   enum { AllocArg };
680 public:
681   CoroAllocaAllocInst *getAlloc() const {
682     return cast<CoroAllocaAllocInst>(getArgOperand(AllocArg));
683   }
684 
685   // Methods to support type inquiry through isa, cast, and dyn_cast:
686   static bool classof(const IntrinsicInst *I) {
687     return I->getIntrinsicID() == Intrinsic::coro_alloca_get;
688   }
689   static bool classof(const Value *V) {
690     return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
691   }
692 };
693 
694 /// This represents the llvm.coro.alloca.free instruction.
695 class LLVM_LIBRARY_VISIBILITY CoroAllocaFreeInst : public IntrinsicInst {
696   enum { AllocArg };
697 public:
698   CoroAllocaAllocInst *getAlloc() const {
699     return cast<CoroAllocaAllocInst>(getArgOperand(AllocArg));
700   }
701 
702   // Methods to support type inquiry through isa, cast, and dyn_cast:
703   static bool classof(const IntrinsicInst *I) {
704     return I->getIntrinsicID() == Intrinsic::coro_alloca_free;
705   }
706   static bool classof(const Value *V) {
707     return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
708   }
709 };
710 
711 } // End namespace llvm.
712 
713 #endif
714