Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-05-10 08:44:38

0001 //===-- CoroInstr.h - Coroutine Intrinsics Instruction Wrappers -*- C++ -*-===//
0002 //
0003 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
0004 // See https://llvm.org/LICENSE.txt for license information.
0005 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
0006 //
0007 //===----------------------------------------------------------------------===//
0008 // This file defines classes that make it really easy to deal with intrinsic
0009 // functions with the isa/dyncast family of functions.  In particular, this
0010 // allows you to do things like:
0011 //
0012 //     if (auto *SF = dyn_cast<CoroSubFnInst>(Inst))
0013 //        ... SF->getFrame() ...
0014 //
0015 // All intrinsic function calls are instances of the call instruction, so these
0016 // are all subclasses of the CallInst class.  Note that none of these classes
0017 // has state or virtual methods, which is an important part of this gross/neat
0018 // hack working.
0019 //
0020 // The helpful comment above is borrowed from llvm/IntrinsicInst.h, we keep
0021 // coroutine intrinsic wrappers here since they are only used by the passes in
0022 // the Coroutine library.
0023 //===----------------------------------------------------------------------===//
0024 
0025 #ifndef LLVM_TRANSFORMS_COROUTINES_COROINSTR_H
0026 #define LLVM_TRANSFORMS_COROUTINES_COROINSTR_H
0027 
0028 #include "llvm/IR/GlobalVariable.h"
0029 #include "llvm/IR/IntrinsicInst.h"
0030 #include "llvm/Support/raw_ostream.h"
0031 
0032 namespace llvm {
0033 
0034 /// This class represents the llvm.coro.subfn.addr instruction.
0035 class CoroSubFnInst : public IntrinsicInst {
0036   enum { FrameArg, IndexArg };
0037 
0038 public:
0039   enum ResumeKind {
0040     RestartTrigger = -1,
0041     ResumeIndex,
0042     DestroyIndex,
0043     CleanupIndex,
0044     IndexLast,
0045     IndexFirst = RestartTrigger
0046   };
0047 
0048   Value *getFrame() const { return getArgOperand(FrameArg); }
0049   ResumeKind getIndex() const {
0050     int64_t Index = getRawIndex()->getValue().getSExtValue();
0051     assert(Index >= IndexFirst && Index < IndexLast &&
0052            "unexpected CoroSubFnInst index argument");
0053     return static_cast<ResumeKind>(Index);
0054   }
0055 
0056   ConstantInt *getRawIndex() const {
0057     return cast<ConstantInt>(getArgOperand(IndexArg));
0058   }
0059 
0060   // Methods to support type inquiry through isa, cast, and dyn_cast:
0061   static bool classof(const IntrinsicInst *I) {
0062     return I->getIntrinsicID() == Intrinsic::coro_subfn_addr;
0063   }
0064   static bool classof(const Value *V) {
0065     return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
0066   }
0067 };
0068 
0069 /// This represents the llvm.coro.alloc instruction.
0070 class CoroAllocInst : public IntrinsicInst {
0071 public:
0072   // Methods to support type inquiry through isa, cast, and dyn_cast:
0073   static bool classof(const IntrinsicInst *I) {
0074     return I->getIntrinsicID() == Intrinsic::coro_alloc;
0075   }
0076   static bool classof(const Value *V) {
0077     return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
0078   }
0079 };
0080 
0081 /// This represents the llvm.coro.await.suspend.{void,bool,handle} instructions.
0082 // FIXME: add callback metadata
0083 // FIXME: make a proper IntrinisicInst. Currently this is not possible,
0084 // because llvm.coro.await.suspend.* can be invoked.
0085 class CoroAwaitSuspendInst : public CallBase {
0086   enum { AwaiterArg, FrameArg, WrapperArg };
0087 
0088 public:
0089   Value *getAwaiter() const { return getArgOperand(AwaiterArg); }
0090 
0091   Value *getFrame() const { return getArgOperand(FrameArg); }
0092 
0093   Function *getWrapperFunction() const {
0094     return cast<Function>(getArgOperand(WrapperArg));
0095   }
0096 
0097   // Methods to support type inquiry through isa, cast, and dyn_cast:
0098   static bool classof(const CallBase *CB) {
0099     if (const Function *CF = CB->getCalledFunction()) {
0100       auto IID = CF->getIntrinsicID();
0101       return IID == Intrinsic::coro_await_suspend_void ||
0102              IID == Intrinsic::coro_await_suspend_bool ||
0103              IID == Intrinsic::coro_await_suspend_handle;
0104     }
0105 
0106     return false;
0107   }
0108 
0109   static bool classof(const Value *V) {
0110     return isa<CallBase>(V) && classof(cast<CallBase>(V));
0111   }
0112 };
0113 
0114 /// This represents a common base class for llvm.coro.id instructions.
0115 class AnyCoroIdInst : public IntrinsicInst {
0116 public:
0117   CoroAllocInst *getCoroAlloc() {
0118     for (User *U : users())
0119       if (auto *CA = dyn_cast<CoroAllocInst>(U))
0120         return CA;
0121     return nullptr;
0122   }
0123 
0124   IntrinsicInst *getCoroBegin() {
0125     for (User *U : users())
0126       if (auto *II = dyn_cast<IntrinsicInst>(U))
0127         if (II->getIntrinsicID() == Intrinsic::coro_begin ||
0128             II->getIntrinsicID() == Intrinsic::coro_begin_custom_abi)
0129           return II;
0130     llvm_unreachable("no coro.begin associated with coro.id");
0131   }
0132 
0133   // Methods to support type inquiry through isa, cast, and dyn_cast:
0134   static bool classof(const IntrinsicInst *I) {
0135     auto ID = I->getIntrinsicID();
0136     return ID == Intrinsic::coro_id || ID == Intrinsic::coro_id_retcon ||
0137            ID == Intrinsic::coro_id_retcon_once ||
0138            ID == Intrinsic::coro_id_async;
0139   }
0140 
0141   static bool classof(const Value *V) {
0142     return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
0143   }
0144 };
0145 
0146 /// This represents the llvm.coro.id instruction.
0147 class CoroIdInst : public AnyCoroIdInst {
0148   enum { AlignArg, PromiseArg, CoroutineArg, InfoArg };
0149 
0150 public:
0151   AllocaInst *getPromise() const {
0152     Value *Arg = getArgOperand(PromiseArg);
0153     return isa<ConstantPointerNull>(Arg)
0154                ? nullptr
0155                : cast<AllocaInst>(Arg->stripPointerCasts());
0156   }
0157 
0158   void clearPromise() {
0159     Value *Arg = getArgOperand(PromiseArg);
0160     setArgOperand(PromiseArg, ConstantPointerNull::get(
0161                                   PointerType::getUnqual(getContext())));
0162     if (isa<AllocaInst>(Arg))
0163       return;
0164     assert((isa<BitCastInst>(Arg) || isa<GetElementPtrInst>(Arg)) &&
0165            "unexpected instruction designating the promise");
0166     // TODO: Add a check that any remaining users of Inst are after coro.begin
0167     // or add code to move the users after coro.begin.
0168     auto *Inst = cast<Instruction>(Arg);
0169     if (Inst->use_empty()) {
0170       Inst->eraseFromParent();
0171       return;
0172     }
0173     Inst->moveBefore(std::next(getCoroBegin()->getIterator()));
0174   }
0175 
0176   // Info argument of coro.id is
0177   //   fresh out of the frontend: null ;
0178   //   outlined                 : {Init, Return, Susp1, Susp2, ...} ;
0179   //   postsplit                : [resume, destroy, cleanup] ;
0180   //
0181   // If parts of the coroutine were outlined to protect against undesirable
0182   // code motion, these functions will be stored in a struct literal referred to
0183   // by the Info parameter. Note: this is only needed before coroutine is split.
0184   //
0185   // After coroutine is split, resume functions are stored in an array
0186   // referred to by this parameter.
0187 
0188   struct Info {
0189     ConstantStruct *OutlinedParts = nullptr;
0190     ConstantArray *Resumers = nullptr;
0191 
0192     bool hasOutlinedParts() const { return OutlinedParts != nullptr; }
0193     bool isPostSplit() const { return Resumers != nullptr; }
0194     bool isPreSplit() const { return !isPostSplit(); }
0195   };
0196   Info getInfo() const {
0197     Info Result;
0198     auto *GV = dyn_cast<GlobalVariable>(getRawInfo());
0199     if (!GV)
0200       return Result;
0201 
0202     assert(GV->isConstant() && GV->hasDefinitiveInitializer());
0203     Constant *Initializer = GV->getInitializer();
0204     if ((Result.OutlinedParts = dyn_cast<ConstantStruct>(Initializer)))
0205       return Result;
0206 
0207     Result.Resumers = cast<ConstantArray>(Initializer);
0208     return Result;
0209   }
0210   Constant *getRawInfo() const {
0211     return cast<Constant>(getArgOperand(InfoArg)->stripPointerCasts());
0212   }
0213 
0214   void setInfo(Constant *C) { setArgOperand(InfoArg, C); }
0215 
0216   Function *getCoroutine() const {
0217     return cast<Function>(getArgOperand(CoroutineArg)->stripPointerCasts());
0218   }
0219   void setCoroutineSelf() {
0220     assert(isa<ConstantPointerNull>(getArgOperand(CoroutineArg)) &&
0221            "Coroutine argument is already assigned");
0222     setArgOperand(CoroutineArg, getFunction());
0223   }
0224 
0225   // Methods to support type inquiry through isa, cast, and dyn_cast:
0226   static bool classof(const IntrinsicInst *I) {
0227     return I->getIntrinsicID() == Intrinsic::coro_id;
0228   }
0229   static bool classof(const Value *V) {
0230     return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
0231   }
0232 };
0233 
0234 /// This represents either the llvm.coro.id.retcon or
0235 /// llvm.coro.id.retcon.once instruction.
0236 class AnyCoroIdRetconInst : public AnyCoroIdInst {
0237   enum { SizeArg, AlignArg, StorageArg, PrototypeArg, AllocArg, DeallocArg };
0238 
0239 public:
0240   void checkWellFormed() const;
0241 
0242   uint64_t getStorageSize() const {
0243     return cast<ConstantInt>(getArgOperand(SizeArg))->getZExtValue();
0244   }
0245 
0246   Align getStorageAlignment() const {
0247     return cast<ConstantInt>(getArgOperand(AlignArg))->getAlignValue();
0248   }
0249 
0250   Value *getStorage() const { return getArgOperand(StorageArg); }
0251 
0252   /// Return the prototype for the continuation function.  The type,
0253   /// attributes, and calling convention of the continuation function(s)
0254   /// are taken from this declaration.
0255   Function *getPrototype() const {
0256     return cast<Function>(getArgOperand(PrototypeArg)->stripPointerCasts());
0257   }
0258 
0259   /// Return the function to use for allocating memory.
0260   Function *getAllocFunction() const {
0261     return cast<Function>(getArgOperand(AllocArg)->stripPointerCasts());
0262   }
0263 
0264   /// Return the function to use for deallocating memory.
0265   Function *getDeallocFunction() const {
0266     return cast<Function>(getArgOperand(DeallocArg)->stripPointerCasts());
0267   }
0268 
0269   // Methods to support type inquiry through isa, cast, and dyn_cast:
0270   static bool classof(const IntrinsicInst *I) {
0271     auto ID = I->getIntrinsicID();
0272     return ID == Intrinsic::coro_id_retcon ||
0273            ID == Intrinsic::coro_id_retcon_once;
0274   }
0275   static bool classof(const Value *V) {
0276     return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
0277   }
0278 };
0279 
0280 /// This represents the llvm.coro.id.retcon instruction.
0281 class CoroIdRetconInst : public AnyCoroIdRetconInst {
0282 public:
0283   // Methods to support type inquiry through isa, cast, and dyn_cast:
0284   static bool classof(const IntrinsicInst *I) {
0285     return I->getIntrinsicID() == Intrinsic::coro_id_retcon;
0286   }
0287   static bool classof(const Value *V) {
0288     return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
0289   }
0290 };
0291 
0292 /// This represents the llvm.coro.id.retcon.once instruction.
0293 class CoroIdRetconOnceInst : public AnyCoroIdRetconInst {
0294 public:
0295   // Methods to support type inquiry through isa, cast, and dyn_cast:
0296   static bool classof(const IntrinsicInst *I) {
0297     return I->getIntrinsicID() == Intrinsic::coro_id_retcon_once;
0298   }
0299   static bool classof(const Value *V) {
0300     return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
0301   }
0302 };
0303 
0304 /// This represents the llvm.coro.id.async instruction.
0305 class CoroIdAsyncInst : public AnyCoroIdInst {
0306   enum { SizeArg, AlignArg, StorageArg, AsyncFuncPtrArg };
0307 
0308 public:
0309   void checkWellFormed() const;
0310 
0311   /// The initial async function context size. The fields of which are reserved
0312   /// for use by the frontend. The frame will be allocated as a tail of this
0313   /// context.
0314   uint64_t getStorageSize() const {
0315     return cast<ConstantInt>(getArgOperand(SizeArg))->getZExtValue();
0316   }
0317 
0318   /// The alignment of the initial async function context.
0319   Align getStorageAlignment() const {
0320     return cast<ConstantInt>(getArgOperand(AlignArg))->getAlignValue();
0321   }
0322 
0323   /// The async context parameter.
0324   Value *getStorage() const {
0325     return getParent()->getParent()->getArg(getStorageArgumentIndex());
0326   }
0327 
0328   unsigned getStorageArgumentIndex() const {
0329     auto *Arg = cast<ConstantInt>(getArgOperand(StorageArg));
0330     return Arg->getZExtValue();
0331   }
0332 
0333   /// Return the async function pointer address. This should be the address of
0334   /// a async function pointer struct for the current async function.
0335   /// struct async_function_pointer {
0336   ///   uint32_t context_size;
0337   ///   uint32_t relative_async_function_pointer;
0338   ///  };
0339   GlobalVariable *getAsyncFunctionPointer() const {
0340     return cast<GlobalVariable>(
0341         getArgOperand(AsyncFuncPtrArg)->stripPointerCasts());
0342   }
0343 
0344   // Methods to support type inquiry through isa, cast, and dyn_cast:
0345   static bool classof(const IntrinsicInst *I) {
0346     auto ID = I->getIntrinsicID();
0347     return ID == Intrinsic::coro_id_async;
0348   }
0349 
0350   static bool classof(const Value *V) {
0351     return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
0352   }
0353 };
0354 
0355 /// This represents the llvm.coro.context.alloc instruction.
0356 class CoroAsyncContextAllocInst : public IntrinsicInst {
0357   enum { AsyncFuncPtrArg };
0358 
0359 public:
0360   GlobalVariable *getAsyncFunctionPointer() const {
0361     return cast<GlobalVariable>(
0362         getArgOperand(AsyncFuncPtrArg)->stripPointerCasts());
0363   }
0364 
0365   // Methods to support type inquiry through isa, cast, and dyn_cast:
0366   static bool classof(const IntrinsicInst *I) {
0367     return I->getIntrinsicID() == Intrinsic::coro_async_context_alloc;
0368   }
0369   static bool classof(const Value *V) {
0370     return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
0371   }
0372 };
0373 
0374 /// This represents the llvm.coro.context.dealloc instruction.
0375 class CoroAsyncContextDeallocInst : public IntrinsicInst {
0376   enum { AsyncContextArg };
0377 
0378 public:
0379   Value *getAsyncContext() const {
0380     return getArgOperand(AsyncContextArg)->stripPointerCasts();
0381   }
0382 
0383   // Methods to support type inquiry through isa, cast, and dyn_cast:
0384   static bool classof(const IntrinsicInst *I) {
0385     return I->getIntrinsicID() == Intrinsic::coro_async_context_dealloc;
0386   }
0387   static bool classof(const Value *V) {
0388     return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
0389   }
0390 };
0391 
0392 /// This represents the llvm.coro.async.resume instruction.
0393 /// During lowering this is replaced by the resume function of a suspend point
0394 /// (the continuation function).
0395 class CoroAsyncResumeInst : public IntrinsicInst {
0396 public:
0397   // Methods to support type inquiry through isa, cast, and dyn_cast:
0398   static bool classof(const IntrinsicInst *I) {
0399     return I->getIntrinsicID() == Intrinsic::coro_async_resume;
0400   }
0401   static bool classof(const Value *V) {
0402     return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
0403   }
0404 };
0405 
0406 /// This represents the llvm.coro.async.size.replace instruction.
0407 class CoroAsyncSizeReplace : public IntrinsicInst {
0408 public:
0409   // Methods to support type inquiry through isa, cast, and dyn_cast:
0410   static bool classof(const IntrinsicInst *I) {
0411     return I->getIntrinsicID() == Intrinsic::coro_async_size_replace;
0412   }
0413   static bool classof(const Value *V) {
0414     return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
0415   }
0416 };
0417 
0418 /// This represents the llvm.coro.frame instruction.
0419 class CoroFrameInst : public IntrinsicInst {
0420 public:
0421   // Methods to support type inquiry through isa, cast, and dyn_cast:
0422   static bool classof(const IntrinsicInst *I) {
0423     return I->getIntrinsicID() == Intrinsic::coro_frame;
0424   }
0425   static bool classof(const Value *V) {
0426     return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
0427   }
0428 };
0429 
0430 /// This represents the llvm.coro.free instruction.
0431 class CoroFreeInst : public IntrinsicInst {
0432   enum { IdArg, FrameArg };
0433 
0434 public:
0435   Value *getFrame() const { return getArgOperand(FrameArg); }
0436 
0437   // Methods to support type inquiry through isa, cast, and dyn_cast:
0438   static bool classof(const IntrinsicInst *I) {
0439     return I->getIntrinsicID() == Intrinsic::coro_free;
0440   }
0441   static bool classof(const Value *V) {
0442     return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
0443   }
0444 };
0445 
0446 /// This class represents the llvm.coro.begin or llvm.coro.begin.custom.abi
0447 /// instructions.
0448 class CoroBeginInst : public IntrinsicInst {
0449   enum { IdArg, MemArg, CustomABIArg };
0450 
0451 public:
0452   AnyCoroIdInst *getId() const {
0453     return cast<AnyCoroIdInst>(getArgOperand(IdArg));
0454   }
0455 
0456   bool hasCustomABI() const {
0457     return getIntrinsicID() == Intrinsic::coro_begin_custom_abi;
0458   }
0459 
0460   int getCustomABI() const {
0461     return cast<ConstantInt>(getArgOperand(CustomABIArg))->getZExtValue();
0462   }
0463 
0464   Value *getMem() const { return getArgOperand(MemArg); }
0465 
0466   // Methods for support type inquiry through isa, cast, and dyn_cast:
0467   static bool classof(const IntrinsicInst *I) {
0468     return I->getIntrinsicID() == Intrinsic::coro_begin ||
0469            I->getIntrinsicID() == Intrinsic::coro_begin_custom_abi;
0470   }
0471   static bool classof(const Value *V) {
0472     return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
0473   }
0474 };
0475 
0476 /// This represents the llvm.coro.save instruction.
0477 class CoroSaveInst : public IntrinsicInst {
0478 public:
0479   // Methods to support type inquiry through isa, cast, and dyn_cast:
0480   static bool classof(const IntrinsicInst *I) {
0481     return I->getIntrinsicID() == Intrinsic::coro_save;
0482   }
0483   static bool classof(const Value *V) {
0484     return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
0485   }
0486 };
0487 
0488 /// This represents the llvm.coro.promise instruction.
0489 class CoroPromiseInst : public IntrinsicInst {
0490   enum { FrameArg, AlignArg, FromArg };
0491 
0492 public:
0493   /// Are we translating from the frame to the promise (false) or from
0494   /// the promise to the frame (true)?
0495   bool isFromPromise() const {
0496     return cast<Constant>(getArgOperand(FromArg))->isOneValue();
0497   }
0498 
0499   /// The required alignment of the promise.  This must match the
0500   /// alignment of the promise alloca in the coroutine.
0501   Align getAlignment() const {
0502     return cast<ConstantInt>(getArgOperand(AlignArg))->getAlignValue();
0503   }
0504 
0505   // Methods to support type inquiry through isa, cast, and dyn_cast:
0506   static bool classof(const IntrinsicInst *I) {
0507     return I->getIntrinsicID() == Intrinsic::coro_promise;
0508   }
0509   static bool classof(const Value *V) {
0510     return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
0511   }
0512 };
0513 
0514 class AnyCoroSuspendInst : public IntrinsicInst {
0515 public:
0516   CoroSaveInst *getCoroSave() const;
0517 
0518   // Methods to support type inquiry through isa, cast, and dyn_cast:
0519   static bool classof(const IntrinsicInst *I) {
0520     return I->getIntrinsicID() == Intrinsic::coro_suspend ||
0521            I->getIntrinsicID() == Intrinsic::coro_suspend_async ||
0522            I->getIntrinsicID() == Intrinsic::coro_suspend_retcon;
0523   }
0524   static bool classof(const Value *V) {
0525     return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
0526   }
0527 };
0528 
0529 /// This represents the llvm.coro.suspend instruction.
0530 class CoroSuspendInst : public AnyCoroSuspendInst {
0531   enum { SaveArg, FinalArg };
0532 
0533 public:
0534   CoroSaveInst *getCoroSave() const {
0535     Value *Arg = getArgOperand(SaveArg);
0536     if (auto *SI = dyn_cast<CoroSaveInst>(Arg))
0537       return SI;
0538     assert(isa<ConstantTokenNone>(Arg));
0539     return nullptr;
0540   }
0541 
0542   bool isFinal() const {
0543     return cast<Constant>(getArgOperand(FinalArg))->isOneValue();
0544   }
0545 
0546   // Methods to support type inquiry through isa, cast, and dyn_cast:
0547   static bool classof(const IntrinsicInst *I) {
0548     return I->getIntrinsicID() == Intrinsic::coro_suspend;
0549   }
0550   static bool classof(const Value *V) {
0551     return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
0552   }
0553 };
0554 
0555 inline CoroSaveInst *AnyCoroSuspendInst::getCoroSave() const {
0556   if (auto Suspend = dyn_cast<CoroSuspendInst>(this))
0557     return Suspend->getCoroSave();
0558   return nullptr;
0559 }
0560 
0561 /// This represents the llvm.coro.suspend.async instruction.
0562 class CoroSuspendAsyncInst : public AnyCoroSuspendInst {
0563 public:
0564   enum {
0565     StorageArgNoArg,
0566     ResumeFunctionArg,
0567     AsyncContextProjectionArg,
0568     MustTailCallFuncArg
0569   };
0570 
0571   void checkWellFormed() const;
0572 
0573   unsigned getStorageArgumentIndex() const {
0574     auto *Arg = cast<ConstantInt>(getArgOperand(StorageArgNoArg));
0575     return Arg->getZExtValue();
0576   }
0577 
0578   Function *getAsyncContextProjectionFunction() const {
0579     return cast<Function>(
0580         getArgOperand(AsyncContextProjectionArg)->stripPointerCasts());
0581   }
0582 
0583   CoroAsyncResumeInst *getResumeFunction() const {
0584     return cast<CoroAsyncResumeInst>(
0585         getArgOperand(ResumeFunctionArg)->stripPointerCasts());
0586   }
0587 
0588   Function *getMustTailCallFunction() const {
0589     return cast<Function>(
0590         getArgOperand(MustTailCallFuncArg)->stripPointerCasts());
0591   }
0592 
0593   // Methods to support type inquiry through isa, cast, and dyn_cast:
0594   static bool classof(const IntrinsicInst *I) {
0595     return I->getIntrinsicID() == Intrinsic::coro_suspend_async;
0596   }
0597   static bool classof(const Value *V) {
0598     return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
0599   }
0600 };
0601 
0602 /// This represents the llvm.coro.suspend.retcon instruction.
0603 class CoroSuspendRetconInst : public AnyCoroSuspendInst {
0604 public:
0605   op_iterator value_begin() { return arg_begin(); }
0606   const_op_iterator value_begin() const { return arg_begin(); }
0607 
0608   op_iterator value_end() { return arg_end(); }
0609   const_op_iterator value_end() const { return arg_end(); }
0610 
0611   iterator_range<op_iterator> value_operands() {
0612     return make_range(value_begin(), value_end());
0613   }
0614   iterator_range<const_op_iterator> value_operands() const {
0615     return make_range(value_begin(), value_end());
0616   }
0617 
0618   // Methods to support type inquiry through isa, cast, and dyn_cast:
0619   static bool classof(const IntrinsicInst *I) {
0620     return I->getIntrinsicID() == Intrinsic::coro_suspend_retcon;
0621   }
0622   static bool classof(const Value *V) {
0623     return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
0624   }
0625 };
0626 
0627 /// This represents the llvm.coro.size instruction.
0628 class CoroSizeInst : public IntrinsicInst {
0629 public:
0630   // Methods to support type inquiry through isa, cast, and dyn_cast:
0631   static bool classof(const IntrinsicInst *I) {
0632     return I->getIntrinsicID() == Intrinsic::coro_size;
0633   }
0634   static bool classof(const Value *V) {
0635     return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
0636   }
0637 };
0638 
0639 /// This represents the llvm.coro.align instruction.
0640 class CoroAlignInst : public IntrinsicInst {
0641 public:
0642   // Methods to support type inquiry through isa, cast, and dyn_cast:
0643   static bool classof(const IntrinsicInst *I) {
0644     return I->getIntrinsicID() == Intrinsic::coro_align;
0645   }
0646   static bool classof(const Value *V) {
0647     return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
0648   }
0649 };
0650 
0651 /// This represents the llvm.end.results instruction.
0652 class CoroEndResults : public IntrinsicInst {
0653 public:
0654   op_iterator retval_begin() { return arg_begin(); }
0655   const_op_iterator retval_begin() const { return arg_begin(); }
0656 
0657   op_iterator retval_end() { return arg_end(); }
0658   const_op_iterator retval_end() const { return arg_end(); }
0659 
0660   iterator_range<op_iterator> return_values() {
0661     return make_range(retval_begin(), retval_end());
0662   }
0663   iterator_range<const_op_iterator> return_values() const {
0664     return make_range(retval_begin(), retval_end());
0665   }
0666 
0667   unsigned numReturns() const {
0668     return std::distance(retval_begin(), retval_end());
0669   }
0670 
0671   // Methods to support type inquiry through isa, cast, and dyn_cast:
0672   static bool classof(const IntrinsicInst *I) {
0673     return I->getIntrinsicID() == Intrinsic::coro_end_results;
0674   }
0675   static bool classof(const Value *V) {
0676     return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
0677   }
0678 };
0679 
0680 class AnyCoroEndInst : public IntrinsicInst {
0681   enum { FrameArg, UnwindArg, TokenArg };
0682 
0683 public:
0684   bool isFallthrough() const { return !isUnwind(); }
0685   bool isUnwind() const {
0686     return cast<Constant>(getArgOperand(UnwindArg))->isOneValue();
0687   }
0688 
0689   bool hasResults() const {
0690     return !isa<ConstantTokenNone>(getArgOperand(TokenArg));
0691   }
0692 
0693   CoroEndResults *getResults() const {
0694     assert(hasResults());
0695     return cast<CoroEndResults>(getArgOperand(TokenArg));
0696   }
0697 
0698   // Methods to support type inquiry through isa, cast, and dyn_cast:
0699   static bool classof(const IntrinsicInst *I) {
0700     auto ID = I->getIntrinsicID();
0701     return ID == Intrinsic::coro_end || ID == Intrinsic::coro_end_async;
0702   }
0703   static bool classof(const Value *V) {
0704     return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
0705   }
0706 };
0707 
0708 /// This represents the llvm.coro.end instruction.
0709 class CoroEndInst : public AnyCoroEndInst {
0710 public:
0711   // Methods to support type inquiry through isa, cast, and dyn_cast:
0712   static bool classof(const IntrinsicInst *I) {
0713     return I->getIntrinsicID() == Intrinsic::coro_end;
0714   }
0715   static bool classof(const Value *V) {
0716     return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
0717   }
0718 };
0719 
0720 /// This represents the llvm.coro.end instruction.
0721 class CoroAsyncEndInst : public AnyCoroEndInst {
0722   enum { FrameArg, UnwindArg, MustTailCallFuncArg };
0723 
0724 public:
0725   void checkWellFormed() const;
0726 
0727   Function *getMustTailCallFunction() const {
0728     if (arg_size() < 3)
0729       return nullptr;
0730 
0731     return cast<Function>(
0732         getArgOperand(MustTailCallFuncArg)->stripPointerCasts());
0733   }
0734 
0735   // Methods to support type inquiry through isa, cast, and dyn_cast:
0736   static bool classof(const IntrinsicInst *I) {
0737     return I->getIntrinsicID() == Intrinsic::coro_end_async;
0738   }
0739   static bool classof(const Value *V) {
0740     return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
0741   }
0742 };
0743 
0744 /// This represents the llvm.coro.alloca.alloc instruction.
0745 class CoroAllocaAllocInst : public IntrinsicInst {
0746   enum { SizeArg, AlignArg };
0747 
0748 public:
0749   Value *getSize() const { return getArgOperand(SizeArg); }
0750   Align getAlignment() const {
0751     return cast<ConstantInt>(getArgOperand(AlignArg))->getAlignValue();
0752   }
0753 
0754   // Methods to support type inquiry through isa, cast, and dyn_cast:
0755   static bool classof(const IntrinsicInst *I) {
0756     return I->getIntrinsicID() == Intrinsic::coro_alloca_alloc;
0757   }
0758   static bool classof(const Value *V) {
0759     return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
0760   }
0761 };
0762 
0763 /// This represents the llvm.coro.alloca.get instruction.
0764 class CoroAllocaGetInst : public IntrinsicInst {
0765   enum { AllocArg };
0766 
0767 public:
0768   CoroAllocaAllocInst *getAlloc() const {
0769     return cast<CoroAllocaAllocInst>(getArgOperand(AllocArg));
0770   }
0771 
0772   // Methods to support type inquiry through isa, cast, and dyn_cast:
0773   static bool classof(const IntrinsicInst *I) {
0774     return I->getIntrinsicID() == Intrinsic::coro_alloca_get;
0775   }
0776   static bool classof(const Value *V) {
0777     return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
0778   }
0779 };
0780 
0781 /// This represents the llvm.coro.alloca.free instruction.
0782 class CoroAllocaFreeInst : public IntrinsicInst {
0783   enum { AllocArg };
0784 
0785 public:
0786   CoroAllocaAllocInst *getAlloc() const {
0787     return cast<CoroAllocaAllocInst>(getArgOperand(AllocArg));
0788   }
0789 
0790   // Methods to support type inquiry through isa, cast, and dyn_cast:
0791   static bool classof(const IntrinsicInst *I) {
0792     return I->getIntrinsicID() == Intrinsic::coro_alloca_free;
0793   }
0794   static bool classof(const Value *V) {
0795     return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
0796   }
0797 };
0798 
0799 } // End namespace llvm.
0800 
0801 #endif // LLVM_TRANSFORMS_COROUTINES_COROINSTR_H