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