Home | History | Annotate | Line # | Download | only in Coroutines
      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